Exemple #1
0
pthreads_monitor_state_t pthreads_stack_next(pthreads_stack_t *stack, zval *value, zend_object **running) {
	pthreads_monitor_state_t state = PTHREADS_MONITOR_RUNNING;
	if (pthreads_monitor_lock(stack->monitor)) {
#define SET_RUNNING_TO(t) *running = t
		do {
			if (!stack->head) {
				if (pthreads_monitor_check(stack->monitor, PTHREADS_MONITOR_JOINED)) {
					state = PTHREADS_MONITOR_JOINED;
					SET_RUNNING_TO(NULL);
					break;
				}
				
				SET_RUNNING_TO(NULL);
				pthreads_monitor_wait(stack->monitor, 0);
			} else {
				pthreads_stack_remove(stack, stack->head, value, PTHREADS_STACK_GARBAGE);
				SET_RUNNING_TO(Z_OBJ_P(value));
				break;
			}
		} while (state != PTHREADS_MONITOR_JOINED);
#undef SET_RUNNING_TO
		pthreads_monitor_unlock(stack->monitor);
	}

	return state;
}
Exemple #2
0
void pthreads_stack_free(pthreads_stack_t *stack) {
	pthreads_monitor_t *monitor = stack->monitor;

	if (pthreads_monitor_lock(monitor)) {
		pthreads_stack_item_t *item = stack->head;
		while (item) {
			pthreads_stack_item_t *r = item;
			zval_ptr_dtor(&item->value);
			item = r->next;
			efree(r);
		}

		if (stack->gc) {
			item = stack->gc->head;		
			while (item) {
				pthreads_stack_item_t *r = item;
				zval_ptr_dtor(&item->value);
				item = r->next;
				efree(r);	
			}
		}

		efree(stack->gc);
		efree(stack);
	
		pthreads_monitor_unlock(monitor);
	}
}
Exemple #3
0
zend_long pthreads_stack_size(pthreads_stack_t *stack) {
	zend_long size = 0;

	if (pthreads_monitor_lock(stack->monitor)) {
		size = stack->size;
		pthreads_monitor_unlock(stack->monitor);
	}
	return size;
}
Exemple #4
0
zend_long pthreads_stack_del(pthreads_stack_t *stack, zval *value) {
	zend_long size = 0;
	
	if (pthreads_monitor_lock(stack->monitor)) {
		size = pthreads_stack_remove(
			stack, stack->head, value, PTHREADS_STACK_FREE);
		pthreads_monitor_unlock(stack->monitor);
	}

	return size;
}
Exemple #5
0
zend_long pthreads_stack_collect(zend_object *std, pthreads_stack_t *stack, pthreads_call_t *call, pthreads_stack_running_function_t running, pthreads_stack_collect_function_t collect) {
	zend_long size = 0, offset = 0;

	if (pthreads_monitor_lock(stack->monitor)) {
		pthreads_stack_item_t *item;

		if (stack->gc) {
			item = stack->gc->head;
			while (item) {
				if (running(std, &item->value)) {
					offset++;
					/* we break out of gc if the worker is executing something on the stack */
					/* this means gc is only performed while the worker is idle */
					/* this means we avoid contention for locks on objects the programmer thinks are executing */
					break;
				}

				if (collect(call, &item->value)) {
					pthreads_stack_item_t *garbage = item;

					pthreads_stack_remove(
						stack->gc, garbage, NULL, PTHREADS_STACK_NOTHING);
					item = garbage->next;
					zval_ptr_dtor(&garbage->value);
					efree(garbage);
					continue;
				}

				item = item->next;
			}

			size = (stack->size + stack->gc->size) + -offset;
		}

		pthreads_monitor_unlock(stack->monitor);
	}

	return size;
}
Exemple #6
0
zend_long pthreads_stack_add(pthreads_stack_t *stack, zval *value) {
	zend_long size = 0;
	pthreads_stack_item_t *item = 
			(pthreads_stack_item_t*) ecalloc(1, sizeof(pthreads_stack_item_t));

	ZVAL_COPY(&item->value, value);

	if (pthreads_monitor_lock(stack->monitor)) {
		size = stack->size;
		pthreads_stack_add_item(stack, item);
		if (!size) {
			pthreads_monitor_notify(stack->monitor);
		}
		size = stack->size;
		pthreads_monitor_unlock(stack->monitor);
	} else {
		zval_ptr_dtor(&item->value);
		efree(item);
		size = -1;
	}

	return size;
}
Exemple #7
0
void pthreads_stack_tohash(pthreads_stack_t *stack, HashTable *hash) {
	zval stacked;
	zval waiting;
	zval gc;

	array_init(&stacked);
	array_init(&waiting);	
	array_init(&gc);

	zend_hash_str_add(Z_ARRVAL(stacked), ":stacked:", sizeof(":stacked:")-1, &waiting);
	zend_hash_str_add(Z_ARRVAL(stacked), ":gc:", sizeof(":gc:")-1, &gc);

	if (pthreads_monitor_lock(stack->monitor)) {
		pthreads_stack_item_t *item = stack->head;
		
		while (item) {
			if (add_next_index_zval(
					&waiting, &item->value)) {
				Z_ADDREF(item->value);
			}
			item = item->next;
		}

		item = stack->gc->head;
		while (item) {
			if (add_next_index_zval(
					&gc, &item->value)) {
				Z_ADDREF(item->value);
			}
			item = item->next;
		}
		pthreads_monitor_unlock(stack->monitor);
	}

	zend_hash_str_add(hash, ":stack:", sizeof(":stack:")-1, &stacked);
}
Exemple #8
0
/* {{{ */
zend_bool pthreads_globals_lock(){
	return pthreads_monitor_lock(PTHREADS_G(monitor));
} /* }}} */
Exemple #9
0
/* {{{ */
void pthreads_write_property(PTHREADS_WRITE_PROPERTY_PASSTHRU_D) {
	pthreads_object_t* threaded = PTHREADS_FETCH_FROM(Z_OBJ_P(object));
	zend_bool nulled = 0;
	zval mstring;

	if (member == NULL || Z_TYPE_P(member) == IS_NULL) {
		pthreads_monitor_lock(threaded->monitor);
		{
			ZVAL_LONG(
				&mstring, zend_hash_next_free_element(threaded->store));
			member = &mstring;
		}
		pthreads_monitor_unlock(threaded->monitor);
	}

	rebuild_object_properties(&threaded->std);

	switch(Z_TYPE_P(value)){
		case IS_UNDEF:
		case IS_STRING:
		case IS_LONG:
		case IS_ARRAY:
		case IS_OBJECT:
		case IS_NULL:
		case IS_DOUBLE:
		case IS_RESOURCE:
		case IS_TRUE:
		case IS_FALSE: {
			zend_long *guard = NULL;
			if (Z_OBJCE_P(object)->__set && (guard = pthreads_get_guard(&threaded->std, member)) && !((*guard) & IN_SET)) {
				zend_fcall_info fci = empty_fcall_info;
				zend_fcall_info_cache fcc = empty_fcall_info_cache;
				zval rv;

				ZVAL_UNDEF(&rv);

				fci.size = sizeof(zend_fcall_info);
				fci.retval = &rv;
				fci.object = &threaded->std;
				zend_fcall_info_argn(&fci, 2, member, value);
				fcc.initialized = 1;
				fcc.function_handler = Z_OBJCE_P(object)->__set;
				fcc.object = &threaded->std;

				(*guard) |= IN_SET;
				zend_call_function(&fci, &fcc);
				(*guard) &= ~IN_SET;

				if (Z_TYPE(rv) != IS_UNDEF)
					zval_dtor(&rv);
				zend_fcall_info_args_clear(&fci, 1);
			} else {
				pthreads_store_write(object, member, value);
			}
		} break;
	
		default: {
			zend_throw_exception_ex(
				spl_ce_RuntimeException, 0,
				"pthreads detected an attempt to use unsupported data (%s) for %s::$%s", 
				zend_get_type_by_const(Z_TYPE_P(value)), 
				ZSTR_VAL(Z_OBJCE_P(object)->name), Z_STRVAL_P(member));
		}
	}
}