Mercurial > hg > nginx
comparison src/os/unix/ngx_freebsd_rfork_thread.c @ 370:54f76b0b8dca
nginx-0.0.7-2004-06-27-22:01:57 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sun, 27 Jun 2004 18:01:57 +0000 |
parents | 55e496a8ece3 |
children | 780e93985b93 |
comparison
equal
deleted
inserted
replaced
369:9c2515d70489 | 370:54f76b0b8dca |
---|---|
6 | 6 |
7 #include <ngx_config.h> | 7 #include <ngx_config.h> |
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 | 9 |
10 /* | 10 /* |
11 * The threads implementation uses the rfork(RFPROC|RFTHREAD|RFMEM) | 11 * The threads implementation uses the rfork(RFPROC|RFTHREAD|RFMEM) syscall |
12 * to create threads. All threads use the stacks of the same size mmap()ed | 12 * to create threads. All threads use the stacks of the same size mmap()ed |
13 * below the main stack. Thus the stack pointer is used to determine | 13 * below the main stack. Thus the current thread id is determinated through |
14 * the current thread id. | 14 * the stack pointer. |
15 * | 15 * |
16 * The mutex implementation uses the ngx_atomic_cmp_set() operation | 16 * The mutex implementation uses the ngx_atomic_cmp_set() operation |
17 * to acquire mutex and the SysV semaphore to wait on a mutex or to wake up | 17 * to acquire a mutex and the SysV semaphore to wait on a mutex or to wake up |
18 * the waiting threads. | 18 * the waiting threads. The light mutex does not use semaphore, so after |
19 * spinning in the lock the thread calls sched_yield(). However the light | |
20 * mutecies are intended to be used with the "trylock" operation only. | |
19 * | 21 * |
20 * The condition variable implementation uses the SysV semaphore set of two | 22 * The condition variable implementation uses the SysV semaphore set of two |
21 * semaphores. The first is used by the CV mutex, and the second is used | 23 * semaphores. The first is used by the CV mutex, and the second is used |
22 * by CV itself. | 24 * by the CV to signal. |
23 * | 25 * |
24 * This threads implementation currently works on i486 and amd64 | 26 * This threads implementation currently works on i386 (486+) and amd64 |
25 * platforms only. | 27 * platforms only. |
26 */ | 28 */ |
27 | 29 |
28 | 30 |
29 char *ngx_freebsd_kern_usrstack; | 31 char *ngx_freebsd_kern_usrstack; |
30 size_t ngx_thread_stack_size; | 32 size_t ngx_thread_stack_size; |
31 | 33 |
32 | 34 |
33 static size_t rz_size; | 35 static size_t rz_size; |
34 static size_t usable_stack_size; | 36 static size_t usable_stack_size; |
35 static char *last_stack; | 37 static char *last_stack; |
259 } | 261 } |
260 | 262 |
261 | 263 |
262 ngx_mutex_t *ngx_mutex_init(ngx_log_t *log, uint flags) | 264 ngx_mutex_t *ngx_mutex_init(ngx_log_t *log, uint flags) |
263 { | 265 { |
264 int nsem, i; | |
265 ngx_mutex_t *m; | 266 ngx_mutex_t *m; |
266 union semun op; | 267 union semun op; |
267 | 268 |
268 if (!(m = ngx_alloc(sizeof(ngx_mutex_t), log))) { | 269 if (!(m = ngx_alloc(sizeof(ngx_mutex_t), log))) { |
269 return NULL; | 270 return NULL; |
275 if (flags & NGX_MUTEX_LIGHT) { | 276 if (flags & NGX_MUTEX_LIGHT) { |
276 m->semid = -1; | 277 m->semid = -1; |
277 return m; | 278 return m; |
278 } | 279 } |
279 | 280 |
280 nsem = flags & NGX_MUTEX_CV ? 2 : 1; | 281 m->semid = semget(IPC_PRIVATE, 1, SEM_R|SEM_A); |
281 | |
282 m->semid = semget(IPC_PRIVATE, nsem, SEM_R|SEM_A); | |
283 if (m->semid == -1) { | 282 if (m->semid == -1) { |
284 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "semget() failed"); | 283 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "semget() failed"); |
285 return NULL; | 284 return NULL; |
286 } | 285 } |
287 | 286 |
288 op.val = 0; | 287 op.val = 0; |
289 for (i = 0; i < nsem; i++) { | 288 |
290 if (semctl(m->semid, i, SETVAL, op) == -1) { | 289 if (semctl(m->semid, 0, SETVAL, op) == -1) { |
290 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "semctl(SETVAL) failed"); | |
291 | |
292 if (semctl(m->semid, 0, IPC_RMID) == -1) { | |
291 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | 293 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, |
292 "semctl(SETVAL) failed"); | 294 "semctl(IPC_RMID) failed"); |
293 | 295 } |
294 if (semctl(m->semid, 0, IPC_RMID) == -1) { | 296 |
295 ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno, | 297 return NULL; |
296 "semctl(IPC_RMID) failed"); | |
297 } | |
298 | |
299 return NULL; | |
300 } | |
301 } | 298 } |
302 | 299 |
303 return m; | 300 return m; |
304 } | 301 } |
305 | 302 |
386 | 383 |
387 /* | 384 /* |
388 * The number of the waiting threads has been increased | 385 * The number of the waiting threads has been increased |
389 * and we would wait on the SysV semaphore. | 386 * and we would wait on the SysV semaphore. |
390 * A semaphore should wake up us more efficiently than | 387 * A semaphore should wake up us more efficiently than |
391 * a simple usleep(). | 388 * a simple sched_yield() or usleep(). |
392 */ | 389 */ |
393 | 390 |
394 op.sem_num = 0; | 391 op.sem_num = 0; |
395 op.sem_op = -1; | 392 op.sem_op = -1; |
396 op.sem_flg = SEM_UNDO; | 393 op.sem_flg = SEM_UNDO; |
454 | 451 |
455 old = m->lock; | 452 old = m->lock; |
456 | 453 |
457 if (!(old & NGX_MUTEX_LOCK_BUSY)) { | 454 if (!(old & NGX_MUTEX_LOCK_BUSY)) { |
458 ngx_log_error(NGX_LOG_ALERT, m->log, 0, | 455 ngx_log_error(NGX_LOG_ALERT, m->log, 0, |
459 "tring to unlock the free mutex " PTR_FMT, m); | 456 "trying to unlock the free mutex " PTR_FMT, m); |
460 return NGX_ERROR; | 457 return NGX_ERROR; |
461 } | 458 } |
462 | 459 |
463 /* free the mutex */ | 460 /* free the mutex */ |
464 | 461 |
477 "mutex " PTR_FMT " is unlocked", m); | 474 "mutex " PTR_FMT " is unlocked", m); |
478 | 475 |
479 return NGX_OK; | 476 return NGX_OK; |
480 } | 477 } |
481 | 478 |
482 /* check weather we need to wake up a waiting thread */ | 479 /* check whether we need to wake up a waiting thread */ |
483 | 480 |
484 old = m->lock; | 481 old = m->lock; |
485 | 482 |
486 for ( ;; ) { | 483 for ( ;; ) { |
487 if (old & NGX_MUTEX_LOCK_BUSY) { | 484 if (old & NGX_MUTEX_LOCK_BUSY) { |
523 ngx_log_debug1(NGX_LOG_DEBUG_CORE, m->log, 0, | 520 ngx_log_debug1(NGX_LOG_DEBUG_CORE, m->log, 0, |
524 "mutex " PTR_FMT " is unlocked", m); | 521 "mutex " PTR_FMT " is unlocked", m); |
525 | 522 |
526 return NGX_OK; | 523 return NGX_OK; |
527 } | 524 } |
525 | |
526 | |
527 ngx_cv_t *ngx_cv_init(ngx_log_t *log) | |
528 { | |
529 ngx_cv_t *cv; | |
530 u_short val[2]; | |
531 union semun op; | |
532 | |
533 if (!(cv = ngx_alloc(sizeof(ngx_cv_t), log))) { | |
534 return NULL; | |
535 } | |
536 | |
537 cv->mutex.lock = 0; | |
538 cv->mutex.log = log; | |
539 | |
540 cv->mutex.semid = semget(IPC_PRIVATE, 2, SEM_R|SEM_A); | |
541 if (cv->mutex.semid == -1) { | |
542 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "semget() failed"); | |
543 return NULL; | |
544 } | |
545 | |
546 val[0] = 0; | |
547 val[1] = 0; | |
548 op.array = val; | |
549 | |
550 if (semctl(cv->mutex.semid, 0, SETALL, op) == -1) { | |
551 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "semctl(SETALL) failed"); | |
552 | |
553 if (semctl(cv->mutex.semid, 0, IPC_RMID) == -1) { | |
554 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
555 "semctl(IPC_RMID) failed"); | |
556 } | |
557 | |
558 return NULL; | |
559 } | |
560 | |
561 return cv; | |
562 } | |
563 | |
564 | |
565 void ngx_cv_done(ngx_cv_t *cv) | |
566 { | |
567 if (semctl(cv->mutex.semid, 0, IPC_RMID) == -1) { | |
568 ngx_log_error(NGX_LOG_ALERT, cv->mutex.log, ngx_errno, | |
569 "semctl(IPC_RMID) failed"); | |
570 } | |
571 | |
572 ngx_free(cv); | |
573 } | |
574 | |
575 | |
576 ngx_int_t ngx_cv_wait(ngx_cv_t *cv) | |
577 { | |
578 struct sembuf op[2]; | |
579 | |
580 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->mutex.log, 0, | |
581 "cv " PTR_FMT " wait", cv); | |
582 | |
583 op[0].sem_num = 0; | |
584 op[0].sem_op = -1; | |
585 op[0].sem_flg = SEM_UNDO; | |
586 | |
587 op[1].sem_num = 1; | |
588 op[1].sem_op = -1; | |
589 op[1].sem_flg = SEM_UNDO; | |
590 | |
591 if (semop(cv->mutex.semid, op, 2) == -1) { | |
592 ngx_log_error(NGX_LOG_ALERT, cv->mutex.log, ngx_errno, | |
593 "semop() failed while waiting on cv " PTR_FMT, cv); | |
594 return NGX_ERROR; | |
595 } | |
596 | |
597 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->mutex.log, 0, | |
598 "cv " PTR_FMT " is waked up", cv); | |
599 | |
600 return NGX_OK; | |
601 } | |
602 | |
603 | |
604 ngx_int_t ngx_cv_signal(ngx_cv_t *cv) | |
605 { | |
606 struct sembuf op[2]; | |
607 | |
608 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->mutex.log, 0, | |
609 "cv " PTR_FMT " to signal", cv); | |
610 | |
611 op[0].sem_num = 0; | |
612 op[0].sem_op = 1; | |
613 op[0].sem_flg = SEM_UNDO; | |
614 | |
615 op[1].sem_num = 1; | |
616 op[1].sem_op = 1; | |
617 op[1].sem_flg = SEM_UNDO; | |
618 | |
619 if (semop(cv->mutex.semid, op, 2) == -1) { | |
620 ngx_log_error(NGX_LOG_ALERT, cv->mutex.log, ngx_errno, | |
621 "semop() failed while signaling cv " PTR_FMT, cv); | |
622 return NGX_ERROR; | |
623 } | |
624 | |
625 ngx_log_debug1(NGX_LOG_DEBUG_CORE, cv->mutex.log, 0, | |
626 "cv " PTR_FMT " is signaled", cv); | |
627 | |
628 return NGX_OK; | |
629 } |