// // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // kernel -- // // Author : Thierry Delisle // Created On : Tue Jan 17 12:27:26 2017 // Last Modified By : Peter A. Buhr // Last Modified On : Tue Apr 10 14:46:49 2018 // Update Count : 10 // #pragma once #include #include "invoke.h" #include "time_t.h" extern "C" { #include } //----------------------------------------------------------------------------- // Locks struct semaphore { __spinlock_t lock; int count; __queue_t(thread_desc) waiting; }; void ?{}(semaphore & this, int count = 1); void ^?{}(semaphore & this); void P (semaphore & this); void V (semaphore & this); //----------------------------------------------------------------------------- // Cluster struct cluster { // Ready queue locks __spinlock_t ready_queue_lock; // Ready queue for threads __queue_t(thread_desc) ready_queue; // Name of the cluster const char * name; // Preemption rate on this cluster Duration preemption_rate; // List of idle processors // __dllist_t(struct processor) idles; }; extern struct cluster * mainCluster; extern Duration default_preemption(); void ?{} (cluster & this, const char * name, Duration preemption_rate); void ^?{}(cluster & this); static inline void ?{} (cluster & this) { this{"Anonymous Cluster", default_preemption()}; } static inline void ?{} (cluster & this, Duration preemption_rate) { this{"Anonymous Cluster", preemption_rate}; } static inline void ?{} (cluster & this, const char * name) { this{name, default_preemption()}; } //----------------------------------------------------------------------------- // Processor enum FinishOpCode { No_Action, Release, Schedule, Release_Schedule, Release_Multi, Release_Multi_Schedule }; //TODO use union, many of these fields are mutually exclusive (i.e. MULTI vs NOMULTI) struct FinishAction { FinishOpCode action_code; thread_desc * thrd; __spinlock_t * lock; __spinlock_t ** locks; unsigned short lock_count; thread_desc ** thrds; unsigned short thrd_count; }; static inline void ?{}(FinishAction & this) { this.action_code = No_Action; this.thrd = NULL; this.lock = NULL; } static inline void ^?{}(FinishAction & this) {} // Processor coroutine processorCtx_t { struct processor * proc; }; // Wrapper around kernel threads struct processor { // Main state // Coroutine ctx who does keeps the state of the processor struct processorCtx_t runner; // Cluster from which to get threads cluster * cltr; // Name of the processor const char * name; // Handle to pthreads pthread_t kernel_thread; // Termination // Set to true to notify the processor should terminate volatile bool do_terminate; // Termination synchronisation semaphore terminated; // RunThread data // Action to do after a thread is ran struct FinishAction finish; // Preemption data // Node which is added in the discrete event simulaiton struct alarm_node_t * preemption_alarm; // If true, a preemption was triggered in an unsafe region, the processor must preempt as soon as possible bool pending_preemption; struct { pthread_mutex_t lock; pthread_cond_t cond; } idle; #ifdef __CFA_DEBUG__ // Last function to enable preemption on this processor const char * last_enable; #endif }; void ?{}(processor & this, const char * name, cluster & cltr); void ^?{}(processor & this); static inline void ?{}(processor & this) { this{ "Anonymous Processor", *mainCluster}; } static inline void ?{}(processor & this, cluster & cltr) { this{ "Anonymous Processor", cltr}; } static inline void ?{}(processor & this, const char * name) { this{name, *mainCluster }; } // Local Variables: // // mode: c // // tab-width: 4 // // End: //