/* * pj_sem_trywait() */ PJ_DEF(pj_status_t) pj_sem_trywait(pj_sem_t *sem) { #if PJ_HAS_THREADS int result; PJ_CHECK_STACK(); PJ_ASSERT_RETURN(sem, PJ_EINVAL); result = sem_trywait( sem->sem ); if (result == 0) { PJ_LOG(6, (sem->obj_name, "Semaphore acquired by thread %s", pj_thread_this()->obj_name)); } if (result == 0) return PJ_SUCCESS; else return PJ_RETURN_OS_ERROR(pj_get_native_os_error()); #else pj_assert( sem == (pj_sem_t*)1 ); return PJ_SUCCESS; #endif }
/* * pj_ioqueue_create() * * Create select ioqueue. */ PJ_DEF(pj_status_t) pj_ioqueue_create( pj_pool_t *pool, pj_size_t max_fd, pj_ioqueue_t **p_ioqueue) { pj_ioqueue_t *ioqueue; pj_status_t rc; pj_lock_t *lock; int i; /* Check that arguments are valid. */ PJ_ASSERT_RETURN(pool != NULL && p_ioqueue != NULL && max_fd > 0, PJ_EINVAL); /* Check that size of pj_ioqueue_op_key_t is sufficient */ PJ_ASSERT_RETURN(sizeof(pj_ioqueue_op_key_t)-sizeof(void*) >= sizeof(union operation_key), PJ_EBUG); ioqueue = pj_pool_alloc(pool, sizeof(pj_ioqueue_t)); ioqueue_init(ioqueue); ioqueue->max = max_fd; ioqueue->count = 0; pj_list_init(&ioqueue->active_list); #if PJ_IOQUEUE_HAS_SAFE_UNREG /* When safe unregistration is used (the default), we pre-create * all keys and put them in the free list. */ /* Mutex to protect key's reference counter * We don't want to use key's mutex or ioqueue's mutex because * that would create deadlock situation in some cases. */ rc = pj_mutex_create_simple(pool, NULL, &ioqueue->ref_cnt_mutex); if (rc != PJ_SUCCESS) return rc; /* Init key list */ pj_list_init(&ioqueue->free_list); pj_list_init(&ioqueue->closing_list); /* Pre-create all keys according to max_fd */ for ( i=0; i<max_fd; ++i) { pj_ioqueue_key_t *key; key = PJ_POOL_ALLOC_T(pool, pj_ioqueue_key_t); key->ref_count = 0; rc = pj_lock_create_recursive_mutex(pool, NULL, &key->lock); if (rc != PJ_SUCCESS) { key = ioqueue->free_list.next; while (key != &ioqueue->free_list) { pj_lock_destroy(key->lock); key = key->next; } pj_mutex_destroy(ioqueue->ref_cnt_mutex); return rc; } pj_list_push_back(&ioqueue->free_list, key); } #endif rc = pj_lock_create_simple_mutex(pool, "ioq%p", &lock); if (rc != PJ_SUCCESS) return rc; rc = pj_ioqueue_set_lock(ioqueue, lock, PJ_TRUE); if (rc != PJ_SUCCESS) return rc; ioqueue->epfd = os_epoll_create(max_fd); if (ioqueue->epfd < 0) { ioqueue_destroy(ioqueue); return PJ_RETURN_OS_ERROR(pj_get_native_os_error()); } /*ioqueue->events = pj_pool_calloc(pool, max_fd, sizeof(struct epoll_event)); PJ_ASSERT_RETURN(ioqueue->events != NULL, PJ_ENOMEM); ioqueue->queue = pj_pool_calloc(pool, max_fd, sizeof(struct queue)); PJ_ASSERT_RETURN(ioqueue->queue != NULL, PJ_ENOMEM); */ PJ_LOG(4, ("pjlib", "epoll I/O Queue created (%p)", ioqueue)); *p_ioqueue = ioqueue; return PJ_SUCCESS; }
/* * pj_sem_create() */ PJ_DEF(pj_status_t) pj_sem_create( pj_pool_t *pool, const char *name, unsigned initial, unsigned max, pj_sem_t **ptr_sem) { #if PJ_HAS_THREADS pj_sem_t *sem; PJ_CHECK_STACK(); PJ_ASSERT_RETURN(pool != NULL && ptr_sem != NULL, PJ_EINVAL); sem = PJ_POOL_ALLOC_T(pool, pj_sem_t); PJ_ASSERT_RETURN(sem, PJ_ENOMEM); #if defined(PJ_DARWINOS) && PJ_DARWINOS!=0 /* MacOS X doesn't support anonymous semaphore */ { char sem_name[PJ_GUID_MAX_LENGTH+1]; pj_str_t nam; /* We should use SEM_NAME_LEN, but this doesn't seem to be * declared anywhere? The value here is just from trial and error * to get the longest name supported. */ # define MAX_SEM_NAME_LEN 23 /* Create a unique name for the semaphore. */ if (PJ_GUID_STRING_LENGTH <= MAX_SEM_NAME_LEN) { nam.ptr = sem_name; pj_generate_unique_string(&nam); sem_name[nam.slen] = '\0'; } else { pj_create_random_string(sem_name, MAX_SEM_NAME_LEN); sem_name[MAX_SEM_NAME_LEN] = '\0'; } /* Create semaphore */ sem->sem = sem_open(sem_name, O_CREAT|O_EXCL, S_IRUSR|S_IWUSR, initial); if (sem->sem == SEM_FAILED) return PJ_RETURN_OS_ERROR(pj_get_native_os_error()); /* And immediately release the name as we don't need it */ sem_unlink(sem_name); } #else sem->sem = PJ_POOL_ALLOC_T(pool, sem_t); if (sem_init( sem->sem, 0, initial) != 0) return PJ_RETURN_OS_ERROR(pj_get_native_os_error()); #endif /* Set name. */ if (!name) { name = "sem%p"; } if (strchr(name, '%')) { pj_ansi_snprintf(sem->obj_name, PJ_MAX_OBJ_NAME, name, sem); } else { strncpy(sem->obj_name, name, PJ_MAX_OBJ_NAME); sem->obj_name[PJ_MAX_OBJ_NAME-1] = '\0'; } PJ_LOG(6, (sem->obj_name, "Semaphore created")); *ptr_sem = sem; return PJ_SUCCESS; #else *ptr_sem = (pj_sem_t*)1; return PJ_SUCCESS; #endif }