home   contents  previous      next        up

process.h

Файл process.h содержит определения типа Process и функций управления сопроцессами.

Сопроцесс описывается так же, как и обычная функция, только ее первый параметр p должен быть типа (*Process). p указывает на Process-структуру, в которой размещается дескриптор сопроцесса:

typedef struct Process
Process;
struct Process {
Process *link; /* список инициализированных сопроцессов */ int wsret; /* указатель конца стека */ int *wbase; /* указатель начала стека */ int wssize; /* размер стека */ int *wp; /* начальное значение указателя стека WP */ int nparam; /* количество слов, занимаемых параметрами */ void (*func)(); /* указатель определения функции-сопроцесса */ }; Process *_IMS_AllProc;/* список всех процессов */ #define PROC_HIGH 0 /* высокоприоритетный процесс */ #define PROC_LOW 1 /* низкоприоритетный процесс */

Как правило, в теле функции этот параметр p не используется, что заставляет компилятор выдать предупреждающее сообщение о неиспользуемом параметре. Чтобы воспрепятствовать этому, помещайте оператор p = p; в тело сопроцесса-функции.

Функция

Process *ProcAlloc(void (*func)(), int wssize, int nparam, ...);

выделяет память под дескриптор и рабочую область сопроцесса (стек). Размер стека в байтах указывается параметром wssize. Если wssize=0, то под стек выделяется 4Кбайт. Функция ProcAlloc инициализирует дескриптор, используя функцию

int ProcInit(Process *p, void (*func)(), int *ws, int wssize, int nparam,...);

которая сохраняет в дескрипторе *p указатель на определение функции-сопроцесса func, указатель стека ws, размер стека wssize, "количество параметров" сопроцесса nparam (исключая первый параметр p), записывает в выделенную область стека указанные значения параметров. "Количество параметров сопроцесса" - это количество слов памяти, необходимое для сохранения значений параметров. Если все параметры занимают по одному слову памяти, то количество слов равно количеству параметров.

Функция ProcAlloc возвращает указатель на созданный дескриптор в случае успешного выполнения, иначе результатом является NULL. Функция ProcInit возвращает значение, указывающее успешное(0) или неудачное выполнение(!=0).

Память под стек можно выделять только в куче.

Пример.

#include <process.h>
#define  SIZE 4096
void proc(Process *p, int a, int b, int c)
{ p = p; /* воспрепятствовать выдаче предупреждающего сообщения */
  ...    /* о неиспользуемом параметре p*/
}

char *ws;     /* указатель стека */
Process *pA,  /* указатель дескриптора, создаваемого ProcAlloc */
        *pI;  /* указатель дескриптора, инициализируемого ProcInit */

 /* определить сопроцесс с помощью ProcAlloc */
 if ( (pA=ProcAlloc(proc, 0/*4K*/, 3, 1, 2, 3) ) == NULL)
    abort();

 /* определить сопроцесс с помощью ProcInit */
 if ( (pI = (Process *) malloc(sizeof(Process)) ) == NULL)
    abort();
 if ( (ws = (int*)      malloc(SIZE) )            == NULL)
    abort();
 if (ProcInit(pI, proc, ws, SIZE, 3, 1, 2, 3)) 
    abort();

   /*
   Созданы дескрипторы pA и pI сопроцессов
   для функции proc. Когда сопроцессы будут активированы,
   значения параметров будут a=1, b=2, c=3
   */
Функция ProcParam изменяет значения параметров в ранее созданном дескрипторе неактивного сопроцесса *p.

void ProcParam(Process *p, ...);

Число указываемых в ProcParam параметров должно быть равно числу параметров сопроцесса (исключая первый параметр). Избыточные значения игнорируются, а значения неуказанных параметров не определены.

Пример.

   ProcParam(pI, 3, 3, 2, 1));
  /* Когда сопроцесс будут активирован, 
     значения параметров будут a=3, b=2, c=1
  */

Функции

void ProcAllocClean(Process *p);
void ProcInitClean (Process *p);

исключают дескриптор завершившегося сопроцесса *p из списка инициализированных сопроцессов. Функция ProcAllocClean (ProcInitClean) должна использоваться для сопроцесса, инициализированной функцией ProcAlloc (ProcInit) соответственно.

Функция ProcAllocClean освобождают память, выделенную под стек и дескриптор. Если сопроцесс инициализирован функцией ProcInit, то память стека и дескриптора освобождается самостоятельно после вызова ProcInitClean.

Функции

void ProcRun (Process *p);
void ProcRunHigh(Process *p);
void ProcRunLow (Process *p);

активируют сопроцесс p, который начинает исполняться параллельно с процессом, вызвавшим его. Процесс, инициировавший выполнение сопроцесса, не может ни определить, ни изменить состояние сопроцесса без явно программируемых возможностей (например, каналов). Необходимо следить за тем, чтобы задача не завершилась раньше сопроцессов.

Сопроцесс, активированный функциями ProcRun, ProcRunHigh и ProcRunLow, соответственно имеет приоритет активировавшего ее процесса, высокий приоритет и низкий приоритет.

Следующие функции активируют указанные группы сопроцессов, которые начинают выполняться параллельно друг с другом, а вызвавший их процесс приостанавливается. Он получит управление только тогда, когда завершатся все сопроцессы, активированные им.

void ProcPar (Process *p1, ...);
void ProcParList(Process **plist);
void ProcPriPar (Process *phigh, Process *plow);

Сопроцессы, активированные функциями ProcPar, ProcParList, имеют приоритет вызвавшего их процесса. Список (*p1,...) и массив (**plist) указателей дескрипторов сопроцессов должны завершаться константой NULL. Функция ProcPriPar инициирует выполнение сопроцесса *plow с низким, а сопроцесса *phigh c высоким приоритетами. Функцию нельзя вызывать из высокоприоритетного процесса, поскольку это вызовет фатальную ошибку.

Приоритет, который имеет выполняющийся процесс, можно узнать с помощью функции

int ProcGetPriority(void),

возвращающей 1 (PROC_LOW) для низкоприоритетных процессов и 0 (PROC_HIGH) - для высокоприоритетных процессов.

Пример.

ProcPar(pI,pA, NULL);
Process *p[3];
p[1]=pI; p[2]=pA; p[3]=NULL;
ProcParList(p);
if (ProcGetPriority() == PROC_LOW)
ProcPriPar(pI,PA);

Следующая группа функций позволяет приостановить или завершить выполнение сопроцесса, изменить ее положение в очереди активных процессов. Функция

void ProcAfter(int time);

задерживает выполнение вызвавшего ее процесса до наступления указанного времени time, а функция

void ProcWait(int time);

приостанавливает выполнение процесса на указанное число тиков транспьютера time .

Функция

void ProcStop(void);

завершает выполнение сопроцесса.

Функция

void ProcReschedule(void);

помещает процесс в конец очереди активных процессов (busy wait), ожидающих продолжения выполнения в режиме разделения времени.

Списки и массивы указателей каналов следующих функций должны завершаться значением NULL.

int ProcAlt (Channel * c1, ...);
int ProcSkipAlt (Channel * c1, ...);
int ProcTimerAlt (int time, Channel * c1, ...);

int ProcAltList (Channel ** clist);
int ProcSkipAltList(Channel ** clist);
int ProcTimerAltList(int time, Channel ** clist);

ProcAlt и ProcAltList приостанавливают выполнение вызвавшего их процесса, пока один из указанных каналов не будет готов к вводу данных. Функции возвращают индекс списка параметров для канала, который готов к приему данных. Они не осуществляют ввода данных. Элементы списка и массива нумеруются от 0. Функция ProcAltList возвращает -1, если массив каналов пуст.

ProcSkipAlt и ProcSkipAltList проверяют готовность каналов к вводу данных, не останавливая процесс. Индекс готового к вводу канала возвращается аналогично ProcAlt и ProcAltList. Если ни один канал не готов к вводу, то возвращается значение -1.

ProcTimerAlt и ProcTimerAltList работают аналогично ProcAlt и ProcAltList, но только они возобновляют выполнение процесса при наступлении времени time. Если ни один канал не готов к вводу ко времени time, то функции завершаются и возвращают значение -1.

Пример.

int i;
 i = ProcAlt(pI, pA, NULL);
 switch(i)
 { case  0: /* ввод из канала *pI */    break;
   case  1: /* ввод из канала *pA */    break;
 }

 i = ProcSkipAlt(pI, pA, NULL);
 switch(i)
 { case -1: /* ни один канал не готов к вводу */  break;
   case  0: /* ввод из канала *pI */    break;
   case  1: /* ввод из канала *pA */    break;
 }

 i = ProcTimerAlt( ProcTimePlus(ProcTime(),50000), pI, pA, NULL);
 switch(i)
 { case -1: /* время истекло      */    break;
   case  0: /* ввод из канала *pI */    break;
   case  1: /* ввод из канала *pA */    break;
 }


home   contents  previous      next        up