2
0
Эх сурвалжийг харах

Added basic support for Unix processors

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@8163 8c9fc860-2736-0410-a75d-ab315db34111
negelef 7 жил өмнө
parent
commit
80d2a9002d

+ 33 - 3
source/Linux.AMD64.Unix.Mod

@@ -144,6 +144,8 @@ CONST
 	PTHREAD_CANCEL_ASYNCHRONOUS	= 0;
 	PTHREAD_CANCEL_DEFERRED	= 1;
 
+	PTHREAD_BARRIER_SERIAL_THREAD* = -1;
+
 	(*--------------------------- Threads -------------------------------*)
 
 TYPE
@@ -164,6 +166,8 @@ TYPE
 	arg_t*		= ARRAY OF CHAR;
 	argv_t*	= ARRAY OF arg_t;
 
+	Sem* = RECORD reserved1-: ARRAY 4 OF ADDRESS END;
+	Barrier* = RECORD reserved1-: ARRAY 3 OF ADDRESS; reserved2-: ARRAY 2 OF WORD END;
 
 CONST
 	(* Thread priorities *)
@@ -435,11 +439,12 @@ VAR
 	pthread_cond_wait: PROCEDURE {C} (cond: ADDRESS; mutex: ADDRESS): WORD;
 	pthread_cond_signal: PROCEDURE {C} (cond: ADDRESS): WORD;
 
-	pthread_create: PROCEDURE {C} (newthread: ADDRESS; attr: ADDRESS; start_routine: PROCEDURE {C} (arg: PROCEDURE): ADDRESS; arg: PROCEDURE): WORD;
-	pthread_exit: PROCEDURE {C} (thr: ADDRESS);
+	pthread_create-: PROCEDURE {C} (newthread: ADDRESS; attr: ADDRESS; start_routine: ADDRESS; arg: PROCEDURE): WORD;
+	pthread_exit-: PROCEDURE {C, NORETURN} (thr: ADDRESS);
 	pthread_detach: PROCEDURE {C} (thr: ADDRESS);
 	pthread_kill: PROCEDURE {C} (thr: ADDRESS; sigid: LONGINT): LONGINT;
 	pthread_cancel: PROCEDURE {C} (thr: ADDRESS);
+	pthread_join-: PROCEDURE {C} (thread: Thread_t; return: ADDRESS): WORD;
 	
 	pthread_key_create	: PROCEDURE {C} ( key: ADDRESS; destructor: PROCEDURE {C} ( param: ADDRESS ) ): WORD;
 	pthread_setspecific	: PROCEDURE {C} ( key: Key_t; value: ADDRESS ): WORD;
@@ -449,7 +454,7 @@ VAR
 	pthread_attr_setscope: PROCEDURE {C}(attr: ADDRESS; set: WORD);
 	pthread_attr_setdetachstate: PROCEDURE {C}(attr: ADDRESS; set: WORD);
 	pthread_attr_setstacksize: PROCEDURE {C}(attr: ADDRESS; stackSize: SIZE);
-	pthread_self: PROCEDURE {C} (): Thread_t;
+	pthread_self-: PROCEDURE {C} (): Thread_t;
 
 	sched_get_priority_max: PROCEDURE {C} (policy: LONGINT): LONGINT;
 	sched_get_priority_min: PROCEDURE {C} (policy: LONGINT): LONGINT;
@@ -467,6 +472,18 @@ VAR
 	sigaltstack: PROCEDURE {C} (ss, oss: ADDRESS): LONGINT;
 	pthread_sigmask: PROCEDURE {C}(how: LONGINT; set: ADDRESS; oldset: ADDRESS): LONGINT;
 
+	sem_init-: PROCEDURE {C} (sem: ADDRESS; pshared: WORD; value: WORD): WORD;
+	sem_wait-: PROCEDURE {C} (sem: ADDRESS): WORD;
+	sem_post-: PROCEDURE {C} (sem: ADDRESS): WORD;
+	sem_destroy-: PROCEDURE {C} (sem: ADDRESS): WORD;
+
+	pthread_barrier_init-: PROCEDURE {C} (barrier: ADDRESS; attr: ADDRESS; count: WORD): WORD;
+	pthread_barrier_wait-: PROCEDURE {C} (barrier: ADDRESS): WORD;
+	pthread_barrier_destroy-: PROCEDURE {C} (barrier: ADDRESS): WORD;
+
+	pthread_getaffinity_np-: PROCEDURE {C} (thread: Thread_t; cpusetsize: SIZE; cpuset: ADDRESS): WORD;
+	pthread_setaffinity_np-: PROCEDURE {C} (thread: Thread_t; cpusetsize: SIZE; cpuset: ADDRESS): WORD;
+
 	(*pid: return param for process id. Only set if initialized non-null. path: pointer to string denoting the executable. file_actions: modify which files are open for the new process, if NIL it inherits open files from parent process. attrp: sets process groups, scheduler, signals etc, leave NIL. argv, evp: char** to the arguments and env. variables*)
 	posix_spawnp- 	: PROCEDURE {C} (pid: ADDRESS; path: ADDRESS; file_actions: ADDRESS; attrp: ADDRESS; argv: ADDRESS ; envp: ADDRESS): LONGINT;
 	(*more restrictive than spawnp*)
@@ -1088,6 +1105,7 @@ VAR
 		Dlsym( libp, "pthread_detach", ADDRESSOF(pthread_detach) );
 		Dlsym( libp, "pthread_cancel", ADDRESSOF(pthread_cancel) );
 		Dlsym( libp, "pthread_kill", ADDRESSOF(pthread_kill) );
+		Dlsym( libp, "pthread_join", ADDRESSOF(pthread_join) );
 		
 		Dlsym( libp, "pthread_key_create", ADDRESSOF( pthread_key_create ) );
 		Dlsym( libp, "pthread_getspecific", ADDRESSOF( pthread_getspecific ) );
@@ -1102,6 +1120,18 @@ VAR
 		Dlsym( libp, "pthread_attr_setstacksize", ADDRESSOF(pthread_attr_setstacksize) );
 		Dlsym( libp, "pthread_self", ADDRESSOF(pthread_self) );
 
+		Dlsym( libp, "sem_init", ADDRESSOF(sem_init) );
+		Dlsym( libp, "sem_wait", ADDRESSOF(sem_wait) );
+		Dlsym( libp, "sem_post", ADDRESSOF(sem_post) );
+		Dlsym( libp, "sem_destroy", ADDRESSOF(sem_destroy) );
+
+		Dlsym( libp, "pthread_barrier_init", ADDRESSOF(pthread_barrier_init) );
+		Dlsym( libp, "pthread_barrier_wait", ADDRESSOF(pthread_barrier_wait) );
+		Dlsym( libp, "pthread_barrier_destroy", ADDRESSOF(pthread_barrier_destroy) );
+
+		Dlsym( libp, "pthread_getaffinity_np", ADDRESSOF(pthread_getaffinity_np) );
+		Dlsym( libp, "pthread_setaffinity_np", ADDRESSOF(pthread_setaffinity_np) );
+
 		Dlsym( libc, "posix_spawnp", ADDRESSOF(posix_spawnp) );
 		Dlsym( libc, "posix_spawn", ADDRESSOF(posix_spawn) );
 

+ 99 - 0
source/Unix.Processors.Mod

@@ -0,0 +1,99 @@
+(* Unix runtime support for processors *)
+(* Copyright (C) Florian Negele *)
+
+MODULE Processors;
+
+IMPORT Unix;
+
+(** Indicates the maximal number of logical processors that are supported by the system. *)
+CONST Maximum* = MAX (SET) - MIN (SET) + 1;
+
+(** Holds the actual number of processors in the system. *)
+VAR count-: SIZE;
+
+VAR affinityMask: SET;
+VAR semaphore: Unix.Sem;
+VAR barrier: Unix.Barrier;
+VAR thread: ARRAY Maximum OF Unix.Thread_t;
+
+(** Returns the unique index of the processor executing this procedure call. *)
+PROCEDURE GetCurrentIndex- EXTERN "Activities.GetCurrentProcessorIndex" (): SIZE;
+
+(** Suspends the execution of the current processor. *)
+(** A suspended processor must be resumed by a call to the ResumeAnyProcessor procedure. *)
+PROCEDURE SuspendCurrentProcessor-;
+BEGIN {UNCOOPERATIVE, UNCHECKED}
+	ASSERT (count > 1);
+	ASSERT (Unix.sem_wait (ADDRESS OF semaphore) = 0);
+END SuspendCurrentProcessor;
+
+(** Resumes the execution of all suspended processors. *)
+PROCEDURE ResumeAllProcessors-;
+BEGIN {UNCOOPERATIVE, UNCHECKED}
+	ASSERT (count > 1);
+	ASSERT (Unix.sem_post (ADDRESS OF semaphore) = 0);
+END ResumeAllProcessors;
+
+(** Starts the execution of all available processors. *)
+PROCEDURE StartAll-;
+BEGIN {UNCOOPERATIVE, UNCHECKED}
+	ASSERT (count > 1);
+	IF Unix.pthread_barrier_wait (ADDRESS OF barrier) = Unix.PTHREAD_BARRIER_SERIAL_THREAD THEN
+		ASSERT (Unix.pthread_barrier_destroy (ADDRESS OF barrier) = 0);
+	END;
+END StartAll;
+
+(* Start routine for each Posix thread. *)
+PROCEDURE {NORETURN} Start (arg: ADDRESS);
+PROCEDURE Execute EXTERN "Activities.Execute" (procedure: PROCEDURE);
+PROCEDURE Idle EXTERN "Activities.Idle";
+BEGIN {UNCOOPERATIVE, UNCHECKED}
+	StartAll;
+	Execute (Idle);
+	Unix.pthread_exit (0);
+END Start;
+
+(** Initializes the module by enumerating all available processors. *)
+(** The number of concurrent threads corresponds to the number of slots in the affinity mask of the current process. *)
+PROCEDURE Initialize-;
+VAR self: Unix.Thread_t; mask: SET; i: SIZE; length: WORD;
+BEGIN {UNCOOPERATIVE, UNCHECKED}
+	self := Unix.pthread_self ();
+	ASSERT (Unix.sem_init (ADDRESS OF semaphore, 0, 0) = 0);
+	ASSERT (Unix.pthread_getaffinity_np (self, SIZE OF SET, ADDRESS OF affinityMask) = 0);
+	length := 0; FOR i := 0 TO Maximum - 1 DO IF i IN affinityMask THEN INC (length) END END;
+	ASSERT (Unix.pthread_barrier_init (ADDRESS OF barrier, NIL, length) = 0);
+
+	count := 0;
+	FOR i := 0 TO Maximum - 1 DO
+		IF i IN affinityMask THEN
+			INC (count);
+
+			IF count = 1 THEN
+				thread[i] := self;
+			ELSE
+				ASSERT (Unix.pthread_create (ADDRESS OF thread[i], NIL, Start, NIL) = 0);
+			END;
+
+			mask := {i};
+			ASSERT (Unix.pthread_setaffinity_np (thread[i], SIZE OF SET, ADDRESS OF mask) = 0);
+		ELSE
+			thread[i] := self;
+		END;
+	END;
+END Initialize;
+
+(** Terminates the module and waits for all other processors to stop their execution. *)
+PROCEDURE Terminate-;
+VAR self: Unix.Thread_t; i: SIZE;
+BEGIN {UNCOOPERATIVE, UNCHECKED}
+	self := Unix.pthread_self ();
+	FOR i := 0 TO Maximum - 1 DO
+		IF thread[i] # self THEN
+			ASSERT (Unix.pthread_join (thread[i], NIL) = 0);
+		END;
+	END;
+	ASSERT (Unix.sem_destroy (ADDRESS OF semaphore) = 0);
+END Terminate;
+
+END Processors.