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 }