/* {{{ push an item onto the work buffer */ int pthreads_stack_push(PTHREAD thread, PTHREAD work TSRMLS_DC) { int acquire = 0; int counted = -1; acquire = pthread_mutex_lock(thread->lock); if (acquire == SUCCESS || acquire == EDEADLK) { zend_llist *stack = &thread->stack->objects; if (stack) { zend_llist_add_element( stack, &work ); counted = stack->count; } else counted = -1; if (acquire != EDEADLK) pthread_mutex_unlock(thread->lock); } else zend_error(E_ERROR, "pthreads has suffered an internal error and cannot continue: %d", acquire); if (counted > 0) { if (pthreads_state_isset(thread->state, PTHREADS_ST_WAITING TSRMLS_CC)) { pthreads_unset_state(thread, PTHREADS_ST_WAITING TSRMLS_CC); } } return counted; } /* }}} */
/* {{{ set state bits on a thread, timeout where appropriate/required */ int pthreads_set_state_ex(PTHREAD thread, int mask, long timeout) { struct timeval now; struct timespec until; int wacquire = 0, timed = 0, result = -1; if (timeout>0L) { if (gettimeofday(&now, NULL)==SUCCESS) { long nsec = timeout * 1000; if (nsec > 1000000000L) { until.tv_sec = now.tv_sec + (nsec / 1000000000L); until.tv_nsec = (now.tv_usec * 1000) + (nsec % 1000000000L); } else { until.tv_sec = now.tv_sec; until.tv_nsec = (now.tv_usec * 1000) + timeout; } timed=1; } } pthreads_state_set(thread->state, mask); switch(mask){ case PTHREADS_ST_WAITING: { wacquire = PTHREADS_WLOCK(thread); if (wacquire == SUCCESS || wacquire == EDEADLK) { do { if (timed) { result=!pthread_cond_timedwait(thread->sync, thread->wait, &until); } else result=!pthread_cond_wait(thread->sync, thread->wait); } while(pthreads_state_isset(thread->state, PTHREADS_ST_WAITING)); if (wacquire != EDEADLK) PTHREADS_WUNLOCK(thread); } else zend_error(E_WARNING, "pthreads may have expereinced an internal error, I mean, really, who knows ?"); } break; case PTHREADS_ST_RUNNING: pthreads_globals_add(thread); break; } return result; } /* }}} */
/* {{{ push an item onto the work buffer */ int pthreads_stack_push(PTHREAD thread, PTHREAD work) { int acquire = 0; int counted = -1; acquire = PTHREADS_LOCK(thread); if (acquire == SUCCESS || acquire == EDEADLK) { thread->worker = 1; zend_llist_add_element(thread->stack, &work); counted = thread->stack->count; if (acquire != EDEADLK) PTHREADS_UNLOCK(thread); } else zend_error(E_ERROR, "pthreads has suffered an internal error and cannot continue: %d", acquire); if (counted > 0) { if (pthreads_state_isset(thread->state, PTHREADS_ST_WAITING)) { PTHREADS_NOTIFY(thread); } } return counted; } /* }}} */
/* {{{ push an item onto the work buffer */ size_t pthreads_stack_push(PTHREAD thread, PTHREAD work TSRMLS_DC) { zend_bool locked; size_t counted = 0L; if (pthreads_lock_acquire(thread->lock, &locked TSRMLS_CC)) { zend_llist *stack = &thread->stack->objects; if (stack) { zend_llist_add_element( stack, &work ); counted = stack->count; } pthreads_lock_release(thread->lock, locked TSRMLS_CC); if (counted > 0L) { if (pthreads_state_isset(thread->state, PTHREADS_ST_WAITING TSRMLS_CC)) { pthreads_unset_state(thread, PTHREADS_ST_WAITING TSRMLS_CC); } } } return counted; } /* }}} */