source: libcfa/src/concurrency/thread.cfa @ 5d3d281

Last change on this file since 5d3d281 was 5d3d281, checked in by Michael Brooks <mlbrooks@…>, 7 days ago

Remove autogen forward declarations, which are never needed, and cause warnings about static declarations without definitions.

Intended to fix the failing test from previous commit.

Autogen forward declarations are never needed because they do not depend on each other, much less with mutual recursion.

Consequences:

  • tests/.expect/(5 tests).(3 archs).txt: Accept generated code that lacks autogen forward declarations
  • libcfa/src/concurrency/thread.*: Remove unused dependency on destructor from constructor (via thrd_start), by splitting trait is_thread with is_basic_thread
  • Property mode set to 100644
File size: 7.2 KB
RevLine 
[78b3f52]1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
[75a17f1]7// thread.c --
[78b3f52]8//
9// Author           : Thierry Delisle
[f07e037]10// Created On       : Tue Jan 17 12:27:26 2017
[6b0b624]11// Last Modified By : Peter A. Buhr
[16e6905]12// Last Modified On : Sun Sep  3 08:25:21 2023
13// Update Count     : 105
[78b3f52]14//
15
[2026bb6]16#define __cforall_thread__
17
[58b6d1b]18#include "thread.hfa"
[78b3f52]19
[ab8c6a6]20#include "exception.hfa"
[b035046]21#include "kernel/private.hfa"
22#include "limits.hfa"
[8118303]23
24#define __CFA_INVOKE_PRIVATE__
25#include "invoke.h"
26
[dd46fd3]27extern size_t __global_random_seed;
28extern size_t __global_random_prime;
[d2ad151]29extern bool __global_random_mask;
[2210cfc]30
[c18bf9e]31#pragma GCC visibility push(default)
32
[8118303]33//-----------------------------------------------------------------------------
34// Thread ctors and dtors
[2210cfc]35void ?{}( thread$ & this, const char * const name, cluster & cl, void * storage, size_t storageSize ) with( this ) {
[121be3e]36        context{ 0p, 0p };
[de6319f]37        self_cor{ name, storage, storageSize };
[6a77224]38        ticket = TICKET_RUNNING;
[e8e457e]39        state = Start;
[3381ed7]40        preempted = __NO_PREEMPTION;
[ab5baab]41        corctx_flag = false;
[82c948c]42        curr_cor = &self_cor;
[65deb18]43        self_mon.owner = &this;
44        self_mon.recursion = 1;
45        self_mon_p = &self_mon;
[de6319f]46        curr_cluster = &cl;
[15c93d8]47        rdy_link.next = 0p;
48        rdy_link.ts   = MAX;
[1553a55]49        user_link.next = 0p;
50        user_link.prev = 0p;
51        cltr_link.next = 0p;
52        cltr_link.prev = 0p;
[24e321c]53        preferred = ready_queue_new_preferred();
[89eff25]54        last_proc = 0p;
[beeff61e]55    link_node = 0p;
[dd46fd3]56        PRNG_SET_SEED( random_state, __global_random_mask ? __global_random_prime : __global_random_prime ^ rdtscl() );
[b4b63e8]57        #if defined( __CFA_WITH_VERIFY__ )
[878cfcc]58                executing = 0p;
[ac12f1f]59                canary = 0x0D15EA5E0D15EA5Ep;
[b4b63e8]60        #endif
[de94a60]61
[f835806]62        doregister(curr_cluster, this);
[65deb18]63        monitors{ &self_mon_p, 1, (fptr_t)0 };
[8118303]64}
65
[e84ab3d]66void ^?{}(thread$& this) with( this ) {
[b4b63e8]67        #if defined( __CFA_WITH_VERIFY__ )
[ac12f1f]68                canary = 0xDEADDEADDEADDEADp;
[b4b63e8]69        #endif
[a1a17a74]70        unregister(curr_cluster, this);
[65deb18]71        ^self_cor{};
[8118303]72}
73
[fd54fef]74forall(T &)
[ab8c6a6]75void copy(ThreadCancelled(T) * dst, ThreadCancelled(T) * src) {
76        dst->virtual_table = src->virtual_table;
77        dst->the_thread = src->the_thread;
78        dst->the_exception = src->the_exception;
79}
80
[fd54fef]81forall(T &)
[ab8c6a6]82const char * msg(ThreadCancelled(T) *) {
[ecfd758]83        return "ThreadCancelled(...)";
[ab8c6a6]84}
85
[fd54fef]86forall(T &)
[ab8c6a6]87static void default_thread_cancel_handler(ThreadCancelled(T) & ) {
[ecfd758]88        // Improve this error message, can I do formatting?
[ab8c6a6]89        abort( "Unhandled thread cancellation.\n" );
90}
91
[c3b9d639]92forall(T & | is_thread(T) | IS_EXCEPTION(ThreadCancelled(T))
93    | { EHM_DEFAULT_VTABLE(ThreadCancelled(T)); })
[ab8c6a6]94void ?{}( thread_dtor_guard_t & this,
[8edbe40]95                T & thrd, void(*cancelHandler)(ThreadCancelled(T) &)) {
[e84ab3d]96        monitor$ * m = get_monitor(thrd);
97        thread$ * desc = get_thread(thrd);
[3ea8ad1]98
99        // Setup the monitor guard
[ab8c6a6]100        void (*dtor)(T& mutex this) = ^?{};
[8edbe40]101        bool join = cancelHandler != (void(*)(ThreadCancelled(T)&))0;
[ab8c6a6]102        (this.mg){&m, (void(*)())dtor, join};
[342be43]103
[3ea8ad1]104
105        /* paranoid */ verifyf( Halted == desc->state || Cancelled == desc->state, "Expected thread to be Halted or Cancelled, was %d\n", (int)desc->state );
106
[342be43]107        // After the guard set-up and any wait, check for cancellation.
108        struct _Unwind_Exception * cancellation = desc->self_cor.cancellation;
109        if ( likely( 0p == cancellation ) ) {
110                return;
111        } else if ( Cancelled == desc->state ) {
112                return;
113        }
114        desc->state = Cancelled;
[8edbe40]115        void(*defaultResumptionHandler)(ThreadCancelled(T) &) =
[fcd0b9d7]116                join ? cancelHandler : default_thread_cancel_handler;
[342be43]117
118        // TODO: Remove explitate vtable set once trac#186 is fixed.
[8edbe40]119        ThreadCancelled(T) except;
120        except.virtual_table = &_default_vtable;
[342be43]121        except.the_thread = &thrd;
122        except.the_exception = __cfaehm_cancellation_exception( cancellation );
[ecfd758]123        // Why is this cast required?
[8edbe40]124        throwResume (ThreadCancelled(T) &)except;
[342be43]125
126        except.the_exception->virtual_table->free( except.the_exception );
127        free( cancellation );
128        desc->self_cor.cancellation = 0p;
[ab8c6a6]129}
130
131void ^?{}( thread_dtor_guard_t & this ) {
132        ^(this.mg){};
133}
134
[8118303]135//-----------------------------------------------------------------------------
136// Starting and stopping threads
[5d3d281]137forall( T & | is_basic_thread(T) )
[09f357ec]138void __thrd_start( T & this, void (*main_p)(T &) ) {
[e84ab3d]139        thread$ * this_thrd = get_thread(this);
[8118303]140
[1c273d0]141        disable_interrupts();
[c7a900a]142        __cfactx_start(main_p, get_coroutine(this), this, __cfactx_invoke_thread);
[09f357ec]143
[e8e457e]144        this_thrd->context.[SP, FP] = this_thrd->self_cor.context.[SP, FP];
[ac5816d]145        /* paranoid */ verify( this_thrd->context.SP );
[8118303]146
[24e321c]147        schedule_thread$( this_thrd, UNPARK_LOCAL );
[a3821fa]148        enable_interrupts();
[8118303]149}
150
[8c50aed]151//-----------------------------------------------------------------------------
152// Support for threads that don't ues the thread keyword
[fd54fef]153forall( T & | sized(T) | is_thread(T) | { void ?{}(T&); } )
[65deb18]154void ?{}( scoped(T)& this ) with( this ) {
155        handle{};
[09f357ec]156        __thrd_start(handle, main);
[bd98b58]157}
158
[fd54fef]159forall( T &, P... | sized(T) | is_thread(T) | { void ?{}(T&, P); } )
[65deb18]160void ?{}( scoped(T)& this, P params ) with( this ) {
161        handle{ params };
[09f357ec]162        __thrd_start(handle, main);
[8118303]163}
164
[fd54fef]165forall( T & | sized(T) | is_thread(T) )
[65deb18]166void ^?{}( scoped(T)& this ) with( this ) {
167        ^handle{};
[44264c5]168}
169
[ab8c6a6]170//-----------------------------------------------------------------------------
[c3b9d639]171forall(T & | is_thread(T) | IS_RESUMPTION_EXCEPTION(ThreadCancelled(T))
172        | { EHM_DEFAULT_VTABLE(ThreadCancelled(T)); })
[ab8c6a6]173T & join( T & this ) {
174        thread_dtor_guard_t guard = { this, defaultResumptionHandler };
175        return this;
176}
177
[a167c70c]178//-----------------------------------------------------------------------------
179bool migrate( thread$ * thrd, struct cluster & cl ) {
180        monitor$ * tmon = get_monitor(thrd);
181        monitor$ * __monitors[] = { tmon };
182        monitor_guard_t __guard = { __monitors, 1 };
183        {
184                // if nothing needs to be done, return false
185                if( thrd->curr_cluster == &cl ) return false;
186
187                // are we migrating ourself?
188                const bool local = thrd == active_thread();
189
190                /* paranoid */ verify( !local || &cl != active_cluster() );
191                /* paranoid */ verify( !local || thrd->curr_cluster == active_cluster() );
192                /* paranoid */ verify( !local || thrd->curr_cluster == active_processor()->cltr );
193                /* paranoid */ verify( local || tmon->signal_stack.top->owner->waiting_thread == thrd );
194                /* paranoid */ verify( local || tmon->signal_stack.top );
195
196                // make sure we aren't interrupted while doing this
197                // not as important if we aren't local
198                disable_interrupts();
199
200                // actually move the thread
201                unregister( thrd->curr_cluster, *thrd );
202                thrd->curr_cluster = &cl;
203                doregister( thrd->curr_cluster, *thrd );
204
205                // restore interrupts
206                enable_interrupts();
207
208                // if this is the local thread, we are still running on the old cluster
209                if(local) yield();
210
211                /* paranoid */ verify( !local || &cl == active_cluster() );
212                /* paranoid */ verify( !local || thrd->curr_cluster == active_cluster() );
213                /* paranoid */ verify( !local || thrd->curr_cluster == active_processor()->cltr );
214                /* paranoid */ verify(  local || tmon->signal_stack.top );
215                /* paranoid */ verify(  local || tmon->signal_stack.top->owner->waiting_thread == thrd );
216
217                return true;
218        }
219}
220
[5d1ebb9]221//-----------------------------------------------------------------------------
[2210cfc]222
[20cf96d]223void set_seed( size_t seed ) {
[dd46fd3]224        PRNG_STATE_T & state = active_thread()->random_state;
225        PRNG_SET_SEED( state, seed );
[261e107]226        __global_random_seed = seed;
[dd46fd3]227        __global_random_prime = seed;
[c655650]228        __global_random_mask = true;
[00f5fde]229} // set_seed
[12b5e94a]230
[16e6905]231size_t get_seed( void ) { return __global_random_seed; }
[3ef5905]232
[20cf96d]233size_t prng( void ) {                                                                   // [0,UINT_MAX]
[25ef81d]234        return PRNG_NAME( active_thread()->random_state );
[12b5e94a]235} // prng
[2210cfc]236
[78b3f52]237// Local Variables: //
238// mode: c //
239// tab-width: 4 //
[6a3d2e7]240// End: //
Note: See TracBrowser for help on using the repository browser.