home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume44
/
toy_os
/
part04
/
mult_proc.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1994-09-05
|
4KB
|
137 lines
// This may look like C code, but it is really -*- C++ -*-
/*
************************************************************************
*
* Multiprocessing under VM_UNT - Virtual OS
*
* The present file contains interfaces with the system library
* of VM_UNT.
* Important!
* Turn off optimization while compiling the present flag. This
* would prevent the compiler from keeping too much data in registers
* across the function calls. A call to proc_switching(), either explicit
* or implicit (through the P-semaphor operation), leads potentially to
* the thread switching. As experience shows, some registers would not
* be restored after the thread gets control back.
*
* Note, if the preprocessor symbol DEBUG is set, some debug information
* as to setting/releasing the locks, etc. is printed FYI.
*
************************************************************************
*/
#include "mult_proc.h"
#pragma implementation "mult_proc.h"
#include "myenv.h"
#include <setjmp.h>
#include <std.h>
/*
*------------------------------------------------------------------------
* Semaphores
*/
extern "C" { // VM_UNT library calls
void p(void *);
void v(void *);
int sem_awaited(void *);
void * seminit(const char * name, const int size);
}
// Create a semaphore with a specified name
// and assign an initial value to it
Semaphore::Semaphore(const char * _name, const int in_value)
{
assert( _name != 0 );
assure( in_value >= 0, "Initial value of the semaphore cannot be negative");
strncpy(name,_name,sizeof(name)-1);
value = in_value;
assert( (_sem_ptr = seminit(name,in_value)) != 0 );
#ifdef DEBUG
message("\nSemaphore '%s' (ID=%x), in_value %d has been set up",name,
(int)_sem_ptr,value);
#endif
}
// P-semaphore operation
void Semaphore::operator -- (void)
{
#ifdef DEBUG
message("\nAbout to perform P-operation on '%s' (ID=%x), value %d",
name,(int)_sem_ptr,value);
#endif
value--;
asm("pushl %esi");
::p(_sem_ptr);
asm("popl %esi");
#ifdef DEBUG
message("\nWoke up after sleeping on P-operation on '%s' (ID=%x), value %d",
name,(int)_sem_ptr,value);
#endif
}
// V-semaphore operation
void Semaphore::operator ++ (void)
{
#ifdef DEBUG
message("\nAbout to perform V-operation on '%s' (ID=%x), value %d",
name,(int)_sem_ptr,value);
#endif
value++;
::v(_sem_ptr);
}
// Check to see if somebody is waiting on
// this semaphore
int Semaphore::awaited(void)
{
return ::sem_awaited(_sem_ptr);
}
/*
*------------------------------------------------------------------------
* Threads of CPU control
*/
// System calls in VM_UNT
extern "C" {
// Create a thread. Return 0 if we're
// in the child thread, and 1 otherwise
// (kind of like fork())
int newproc(const char * name, const short priority);
volatile void endproc(void); // Terminate the thread
}
static char Was_stack_saved = 0;
// Create a thread with a specified name
// and have it run the procedure we want
// until it is over
Thread::Thread(const char * name, const short priority, Thread_body((*body)))
{
if( !Was_stack_saved )
{
Was_stack_saved = 1;
extern int _stackinit; // The following instructions save
asm("movl %esp,__stackinit"); // the stack of the calling proc
asm("addl $28,__stackinit"); // 28 = (4+3) long words in stack
}
assert( name != 0 );
if( !newproc(name,priority) )
{ // We're in the child thread now
#ifdef DEBUG
message("\nRunning a thread '%s', priority %d\n",name,priority);
#endif
body();
#ifdef DEBUG
message("\nThread '%s' is through\n",name);
#endif
endproc();
}
// We're in the parent thread now
}