Ejemplo n.º 1
0
/*
doc:	<routine name="rt_processor_application_loop" return_type="void" export="shared">
doc:		<summary> The main loop of a SCOOP processor.
doc:			This is the entry point for every processor and will be the called by
doc:			rt_processor_registry.c:spawn_main(). The root thread of the application will also
doc:			enter this loop after execution of the root feature. </summary>
doc:		<param name="self" type="struct rt_processor*"> The processor object. Must not be NULL. </param>
doc:		<thread_safety> Not safe. </thread_safety>
doc:		<synchronization> Only execute this feature on the thread behind processor 'self'. </synchronization>
doc:	</routine>
*/
rt_shared void rt_processor_application_loop (struct rt_processor* self)
{
	EIF_BOOLEAN is_stopped = EIF_FALSE;

	REQUIRE ("self_not_null", self);

	self->is_active = EIF_FALSE;

	while (!is_stopped) {
		struct rt_message next_job;

			/* When all processors are idle, trigger a
			 * garbage collection cycle. This is sufficient for
			 * program termination, but it isn't useful to free
			 * processors early, before RT_MAX_SCOOP_PROCESSOR_COUNT
			 * has been reached.
			 * TODO: Since the introduction of the early GC technique,
			 * the mechanism here has become obsolete and can be
			 * removed.
			 */
		if (decrement_and_fetch_active_processor_count() == 0
			&& rt_message_channel_is_empty (&self->queue_of_queues)) {
			plsc();
		}

		rt_message_channel_receive_with_gc (&self->queue_of_queues, &next_job);

		if (next_job.message_type == SCOOP_MESSAGE_ADD_QUEUE) {
			increment_active_processor_count();
			self->is_active = EIF_TRUE;
				/* TODO: The information (self->client) is not used by SCOOP itself,
				 * but may be used in the debugger. The idea is to display current
				 * client region of a processor.
				 * However, here we use the client processor instead, because we
				 * don't have the information about the region available. In the future
				 * it may be useful to add a new field to rt_message or in the private
				 * queue that shows the current client. */
			self->client = next_job.sender_processor->pid;

			rt_processor_process_private_queue (self, next_job.queue);

			self->is_active = EIF_FALSE;
			self->client = EIF_NULL_PROCESSOR;
		} else {
			CHECK ("shutdown_message", next_job.message_type == SCOOP_MESSAGE_SHUTDOWN);
			is_stopped = EIF_TRUE;
		}
	}
		/* Check disabled because queue-of-queues might contain multiple shutdown messages. */
	/*CHECK ("empty_queue_of_queues", rt_message_channel_is_empty (&self->queue_of_queues)); */
}
Ejemplo n.º 2
0
/*
doc:	<routine name="rt_request_gc_cycle" return_type="void" export="shared">
doc:		<summary> Run a GC cycle when 'fingerprint' has not changed since the last call. </summary>
doc:		<param name="fingerprint" type="int*"> The fingerprint value. </param>
doc:		<thread_safety> Safe. </thread_safety>
doc:		<synchronization> None required, done internally through atomic operations. </synchronization>
doc:	</routine>
*/
rt_shared void rt_request_gc_cycle (int* fingerprint)
{
	static volatile int gc_fingerprint = 0;
	int previous_fingerprint = * fingerprint;
	int current_fingerprint = RTS_ACAS_I32 (&gc_fingerprint, previous_fingerprint + 1, previous_fingerprint);

	if (current_fingerprint == previous_fingerprint) {
			/* The fingerprint is unchanged since last call, no GC was run, do it now. */
			/* Record newly written fingerprint for the next time. */
		* fingerprint = previous_fingerprint + 1;
			/* Run GC. */
		plsc();
	}
	else {
			/* Record current fingerprint for the next time. */
		* fingerprint = current_fingerprint;
	}
}
Ejemplo n.º 3
0
rt_public main(void)
{
    /* Tests for the local variable stack */

    int i;
    char *a1, *a2;

    printf("> Starting tests for local variable stack.\n");

    /* Check the stack */
    printf(">> Checking the stack management routines.\n");
    printf(">>> Pushing one item.\n");
    epush(&loc_stack, (char *) 0);
    stack_stats();
    printf(">>> Poping the stack.\n");
    epop(&loc_stack, 1);
    stack_stats();

    /* With 10000 items */
    printf(">>> Pushing 20000 items.\n");
    for (i = 0; i < 20000; i++)
        evpush(1, &i);
    stack_stats();
    printf(">>> Poping one item.\n");
    epop(&loc_stack, 1);
    stack_stats();
    printf(">>> Poping 9999 items.\n");
    epop(&loc_stack, 9999);
    stack_stats();
    printf(">>> Poping 10000 items (stack should be empty).\n");
    epop(&loc_stack, 10000);
    stack_stats();

    /* Test collection of local vars */
    printf(">> Testing collection of local vars.\n");
    printf(">>> Creating object A (remembered)\n");
    a1 = emalloc(0);
    eremb(a1);
    printf(">>> Creating object B (not remembered)\n");
    a2 = emalloc(0);
    printf(">>> Pushing A and B in local stack.\n");
    evpush(2, &a1, &a2);
    stack_stats();
    collect_stats();
    printf(">>>> Address of A: 0x%lx\n", a1);
    printf(">>>> Address of B: 0x%lx\n", a2);
    printf(">>> Running a full collection.\n");
    plsc();
    stack_stats();
    collect_stats();
    printf(">>>> Address of A: 0x%lx (changed)\n", a1);
    printf(">>>> Address of B: 0x%lx (changed)\n", a2);
    printf(">>> Running a full collection again.\n");
    plsc();
    stack_stats();
    collect_stats();
    printf(">>>> Address of A: 0x%lx (same as first one)\n", a1);
    printf(">>>> Address of B: 0x%lx (same as first one)\n", a2);

    printf("> End of tests.\n");
    exit(0);
}