2356
2357 /*
2358 * Return true if the signal number is in range
2359 * and the signal code specifies signal queueing.
2360 */
2361 int
2362 sigwillqueue(int sig, int code)
2363 {
2364 if (sig >= 0 && sig < NSIG) {
2365 switch (code) {
2366 case SI_QUEUE:
2367 case SI_TIMER:
2368 case SI_ASYNCIO:
2369 case SI_MESGQ:
2370 return (1);
2371 }
2372 }
2373 return (0);
2374 }
2375
2376 #ifndef UCHAR_MAX
2377 #define UCHAR_MAX 255
2378 #endif
2379
2380 /*
2381 * The entire pool (with maxcount entries) is pre-allocated at
2382 * the first sigqueue/signotify call.
2383 */
2384 sigqhdr_t *
2385 sigqhdralloc(size_t size, uint_t maxcount)
2386 {
2387 size_t i;
2388 sigqueue_t *sq, *next;
2389 sigqhdr_t *sqh;
2390
2391 i = (maxcount * size) + sizeof (sigqhdr_t);
2392 ASSERT(maxcount <= UCHAR_MAX && i <= USHRT_MAX);
2393 sqh = kmem_alloc(i, KM_SLEEP);
2394 sqh->sqb_count = (uchar_t)maxcount;
2395 sqh->sqb_maxcount = (uchar_t)maxcount;
2396 sqh->sqb_size = (ushort_t)i;
2397 sqh->sqb_pexited = 0;
2398 sqh->sqb_sent = 0;
2399 sqh->sqb_free = sq = (sigqueue_t *)(sqh + 1);
2400 for (i = maxcount - 1; i != 0; i--) {
2401 next = (sigqueue_t *)((uintptr_t)sq + size);
2402 sq->sq_next = next;
2403 sq = next;
2404 }
2405 sq->sq_next = NULL;
2406 cv_init(&sqh->sqb_cv, NULL, CV_DEFAULT, NULL);
2407 mutex_init(&sqh->sqb_lock, NULL, MUTEX_DEFAULT, NULL);
2408 return (sqh);
2409 }
2410
2411 static void sigqrel(sigqueue_t *);
2412
2413 /*
2414 * allocate a sigqueue/signotify structure from the per process
2415 * pre-allocated pool.
2416 */
2417 sigqueue_t *
2418 sigqalloc(sigqhdr_t *sqh)
2419 {
2420 sigqueue_t *sq = NULL;
2421
2422 ASSERT(MUTEX_HELD(&curproc->p_lock));
2423
2424 if (sqh != NULL) {
2425 mutex_enter(&sqh->sqb_lock);
2426 if (sqh->sqb_count > 0) {
2427 sqh->sqb_count--;
2428 sq = sqh->sqb_free;
2429 sqh->sqb_free = sq->sq_next;
2430 mutex_exit(&sqh->sqb_lock);
2431 bzero(&sq->sq_info, sizeof (k_siginfo_t));
2432 sq->sq_backptr = sqh;
2433 sq->sq_func = sigqrel;
2434 sq->sq_next = NULL;
2435 sq->sq_external = 0;
2436 } else {
2437 mutex_exit(&sqh->sqb_lock);
2438 }
2439 }
2440 return (sq);
2441 }
2442
2443 /*
2444 * Return a sigqueue structure back to the pre-allocated pool.
2445 */
2446 static void
2447 sigqrel(sigqueue_t *sq)
2448 {
2449 sigqhdr_t *sqh;
2450
2451 /* make sure that p_lock of the affected process is held */
2452
2453 sqh = (sigqhdr_t *)sq->sq_backptr;
|
2356
2357 /*
2358 * Return true if the signal number is in range
2359 * and the signal code specifies signal queueing.
2360 */
2361 int
2362 sigwillqueue(int sig, int code)
2363 {
2364 if (sig >= 0 && sig < NSIG) {
2365 switch (code) {
2366 case SI_QUEUE:
2367 case SI_TIMER:
2368 case SI_ASYNCIO:
2369 case SI_MESGQ:
2370 return (1);
2371 }
2372 }
2373 return (0);
2374 }
2375
2376 #ifndef INT_MAX
2377 #define INT_MAX 2147483647
2378 #endif
2379
2380 #define _SIGQUEUE_PREALLOC 32 /* XXX: log scale? */
2381
2382 /*
2383 * The pre-allocated pool (with _SIGQUEUE_PREALLOC entries) is
2384 * allocated at the first sigqueue/signotify call.
2385 */
2386 sigqhdr_t *
2387 sigqhdralloc(size_t size, uint_t maxcount)
2388 {
2389 size_t i;
2390 sigqueue_t *sq, *next;
2391 sigqhdr_t *sqh;
2392
2393 i = (_SIGQUEUE_PREALLOC * size) + sizeof (sigqhdr_t);
2394 ASSERT(maxcount <= INT_MAX);
2395 sqh = kmem_alloc(i, KM_SLEEP);
2396 sqh->sqb_count = maxcount;
2397 sqh->sqb_maxcount = maxcount;
2398 sqh->sqb_size = i;
2399 sqh->sqb_pexited = 0;
2400 sqh->sqb_sent = 0;
2401 sqh->sqb_free = sq = (sigqueue_t *)(sqh + 1);
2402 for (i = _SIGQUEUE_PREALLOC - 1; i != 0; i--) {
2403 next = (sigqueue_t *)((uintptr_t)sq + size);
2404 sq->sq_next = next;
2405 sq = next;
2406 }
2407 sq->sq_next = NULL;
2408 cv_init(&sqh->sqb_cv, NULL, CV_DEFAULT, NULL);
2409 mutex_init(&sqh->sqb_lock, NULL, MUTEX_DEFAULT, NULL);
2410 return (sqh);
2411 }
2412
2413 static void sigqrel(sigqueue_t *);
2414
2415 /*
2416 * Allocate a sigqueue/signotify structure from the per process
2417 * pre-allocated pool or allocate a new sigqueue/signotify structure
2418 * if the pre-allocated pool is exhausted.
2419 */
2420 sigqueue_t *
2421 sigqalloc(sigqhdr_t *sqh)
2422 {
2423 sigqueue_t *sq = NULL;
2424
2425 ASSERT(MUTEX_HELD(&curproc->p_lock));
2426
2427 if (sqh != NULL) {
2428 mutex_enter(&sqh->sqb_lock);
2429 if (sqh->sqb_count > 0) {
2430 sqh->sqb_count--;
2431 if (sqh->sqb_free == NULL) {
2432 /*
2433 * The pre-allocated pool is exhausted.
2434 */
2435 sq = kmem_alloc(sizeof (sigqueue_t), KM_SLEEP);
2436 sq->sq_func = NULL;
2437 } else {
2438 sq = sqh->sqb_free;
2439 sq->sq_func = sigqrel;
2440 sqh->sqb_free = sq->sq_next;
2441 }
2442 mutex_exit(&sqh->sqb_lock);
2443 bzero(&sq->sq_info, sizeof (k_siginfo_t));
2444 sq->sq_backptr = sqh;
2445 sq->sq_next = NULL;
2446 sq->sq_external = 0;
2447 } else {
2448 mutex_exit(&sqh->sqb_lock);
2449 }
2450 }
2451 return (sq);
2452 }
2453
2454 /*
2455 * Return a sigqueue structure back to the pre-allocated pool.
2456 */
2457 static void
2458 sigqrel(sigqueue_t *sq)
2459 {
2460 sigqhdr_t *sqh;
2461
2462 /* make sure that p_lock of the affected process is held */
2463
2464 sqh = (sigqhdr_t *)sq->sq_backptr;
|