NAME ^

src/thread.c - Thread handling stuff

DESCRIPTION ^

Threads are created by creating new ParrotInterpreter objects.

Functions ^

PARROT_CAN_RETURN_NULL static PMC *make_local_copy(PARROT_INTERP, NOTNULL(Parrot_Interp from), NULLOK(PMC *arg))

Create a local copy of the PMC if necessary. (No copy is made if it is marked shared.) This includes workarounds for Parrot_clone() not doing the Right Thing with subroutines (specifically, code segments aren't preserved and it is difficult to do so as long as Parrot_clone() depends on freezing).

static Shared_gc_info *get_pool(PARROT_INTERP)

Get the shared gc information. TODO: improve the docs here.

PARROT_CAN_RETURN_NULL static PMC *make_local_args_copy(PARROT_INTERP, Parrot_Interp old_interp, PMC *args)

Make a local copy of the corresponding array of arguments.

PMC *pt_shared_fixup(PARROT_INTERP, PMC *pmc)

Fixup a PMC to be sharable. Right now, reassigns the vtable to one owned by some master interpreter, so the PMC can be safely reused after thread death.

In the future the PMC returned might be different than the one passed, e.g., if we need to reallocate the PMC in a different interpreter.

static void pt_thread_signal(NOTNULL(Parrot_Interp self), PARROT_INTERP)

Wakeup a interp which should have called pt_thread_wait().

void pt_thread_wait_with(PARROT_INTERP, Parrot_mutex *mutex)

Wait for this interpreter to be signalled through its condition variable, dealing properly with GC issues. *mutex is assumed locked on entry and will be locked on exit from this function. If a GC run occurs in the middle of this function, then a spurious wakeup may occur.

static void pt_thread_wait(PARROT_INTERP)

Wait for us to be signalled. GC matters are handled correctly. interpreter_array_mutex is assumed held. Spurious wakeups may occur.

PARROT_CAN_RETURN_NULL static void *thread_func(void *arg)

The actual thread function.

Helper functions used also for running plain interpreters ^

void pt_clone_code(Parrot_Interp d, Parrot_Interp s)

Copy/clone the packfile/code from interpreter s to d. All resources are created in d.

static void pt_ns_clone(Parrot_Interp d, PMC *dest_ns, Parrot_Interp s, PMC *source_ns)

Clone all globals from s to d.

void pt_clone_globals(Parrot_Interp d, Parrot_Interp s)

TODO: Not yet documented!!!

void pt_thread_prepare_for_run(Parrot_Interp d, Parrot_Interp s)

Setup code, and TODO ...

ParrotThread methods ^

PMC *pt_transfer_sub(Parrot_Interp d, Parrot_Interp s, NULLOK(PMC *sub))

create a clone of the sub suitable for the other interpreter

int pt_thread_run(PARROT_INTERP, PMC *dest_interp, PMC *sub, PMC *arg)

Run the *sub PMC in a separate thread using interpreter in *dest_interp.

arg should be an array of arguments for the subroutine. int

int pt_thread_run_1(PARROT_INTERP, PMC *dest_interp, PMC *sub, PMC *arg)

Runs a type 1 thread. Nothing is shared, both interpreters are free running without any communication.

int pt_thread_run_2(PARROT_INTERP, PMC *dest_interp, PMC *sub, PMC *arg)

Runs a type 2 thread. No shared variables, threads are communicating by sending messages.

int pt_thread_run_3(PARROT_INTERP, PMC *dest_interp, PMC *sub, PMC *arg)

Run a type 3 thread. Threads may have shared variables and are managed in a thread pool.

void pt_thread_yield(void)

Relinquishes hold on the processor.

static Parrot_Interp pt_check_tid(UINTVAL tid, NOTNULL(const char *from))

Helper function. Check if tid is valid. The caller holds the mutex. Returns the interpreter for tid.

static void mutex_unlock(void *arg)

Unlocks the mutex *arg.

static int is_suspended_for_gc(PARROT_INTERP)

Returns true iff interp is suspended so a global GC can be performed. interpreter_array_mutex must be held.

static QUEUE_ENTRY *remove_queued_suspend_gc(PARROT_INTERP)

XXX should this function be in a different file?

TODO: Not yet documented!!!

static int pt_gc_count_threads(PARROT_INTERP)

interpreter_array_mutex must be held

static void pt_gc_wait_for_stage(PARROT_INTERP, thread_gc_stage_enum from_stage, thread_gc_stage_enum to_stage)

TODO: Not yet documented!!!

static void pt_gc_wakeup_check(PARROT_INTERP)

Check if we need to wake threads to perform garbage collection. This is called after thread death. interpreter_array_mutex is assumed held.

static void pt_suspend_one_for_gc(PARROT_INTERP)

Suspend a single interpreter for GC. interpreter_array_mutex assumed held.

static void pt_suspend_all_for_gc(PARROT_INTERP)

Get all threads to perform a GC run.

void pt_suspend_self_for_gc(PARROT_INTERP)

Suspend this thread for a full GC run.

XXX FIXME -- if GC is blocked, we need to do a GC run as soon as it becomes unblocked.

PMC *pt_thread_join(NOTNULL(Parrot_Interp parent), UINTVAL tid)

Join (wait for) a joinable thread.

void pt_join_threads(PARROT_INTERP)

Possibly wait for other running threads. This is called when destroying interp.

static Parrot_Interp detach(UINTVAL tid)

Helper for detach and kill.

Returns the interpreter, if it didn't finish yet.

void pt_thread_detach(UINTVAL tid)

Detaches (make non-joinable) the thread.

void pt_thread_kill(UINTVAL tid)

Kills the thread.

Threaded interpreter book-keeping ^

void pt_add_to_interpreters(PARROT_INTERP, Parrot_Interp new_interp)

All threaded interpreters are stored in an array. Assumes that caller holds LOCK.

DOD Synchronization Functions ^

void pt_DOD_start_mark(PARROT_INTERP)

DOD is gonna start the mark phase. In the presence of shared PMCs, we can only run one DOD run at a time because PMC->next_for_GC may be changed.

flags are the DOD flags. We check if we need to collect shared objects or not.

TODO - Have a count of shared PMCs and check it during DOD.

TODO - Evaluate if a interpreter lock is cheaper when dod_mark_ptr is updated.

void pt_DOD_mark_root_finished(PARROT_INTERP)

DOD is finished for the root set.

void pt_DOD_stop_mark(PARROT_INTERP)

DOD's mark phase is done.

PARROT_API void Parrot_shared_DOD_block(PARROT_INTERP)

Block stop-the-world DOD runs.

PARROT_API void Parrot_shared_DOD_unblock(PARROT_INTERP)

Unblock stop-the-world DOD runs.


parrot