221 lines
4.8 KiB
C
221 lines
4.8 KiB
C
// This is a personal academic project. Dear PVS-Studio, please check it.
|
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
#include "sem.h"
|
|
|
|
static uint32_t semLock;
|
|
|
|
typedef struct node_t {
|
|
sem_t *sem;
|
|
struct node_t *next;
|
|
} node_t;
|
|
|
|
node_t *firstSem = NULL;
|
|
static char counter = 0;
|
|
|
|
node_t * searchSem(char * name, node_t ** prev) {
|
|
*prev = NULL;
|
|
node_t * aux = firstSem;
|
|
while (aux != NULL) {
|
|
if (!strcmp(name, aux->sem->name))
|
|
break;
|
|
aux = aux->next;
|
|
}
|
|
return aux;
|
|
}
|
|
|
|
sem_t *semOpen(char *name, unsigned int value) {
|
|
enter_region(&semLock);
|
|
|
|
node_t * prev = NULL;
|
|
node_t * aux = searchSem(name, &prev);
|
|
|
|
if (aux != NULL) {
|
|
leave_region(&semLock);
|
|
return aux->sem;
|
|
}
|
|
|
|
sem_t *sem = pvPortMalloc(sizeof(sem_t));
|
|
node_t *node = pvPortMalloc(sizeof(node_t));
|
|
node->sem = sem;
|
|
node->next = firstSem;
|
|
firstSem = node;
|
|
sem->name = pvPortMalloc(MAX_NAME);
|
|
strcpy(sem->name, name);
|
|
sem->value = value;
|
|
sem->entering = NULL;
|
|
sem->last = NULL;
|
|
counter++;
|
|
|
|
leave_region(&semLock);
|
|
|
|
return sem;
|
|
}
|
|
|
|
char semClose(sem_t *sem) {
|
|
if (sem == NULL)
|
|
return EXIT_FAILURE;
|
|
|
|
enter_region(&semLock);
|
|
|
|
node_t *del = NULL;
|
|
|
|
if (firstSem->sem == sem) {
|
|
del = firstSem;
|
|
firstSem = firstSem->next;
|
|
} else {
|
|
node_t *aux = firstSem;
|
|
while (aux != NULL) {
|
|
if (aux->next != NULL) {
|
|
if (aux->next->sem == sem) {
|
|
del = aux->next;
|
|
aux->next = aux->next->next;
|
|
break;
|
|
}
|
|
}
|
|
aux = aux->next;
|
|
}
|
|
}
|
|
|
|
if (del == NULL) {
|
|
leave_region(&semLock);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
pid_t *pid = sem->entering;
|
|
while (pid != NULL) {
|
|
pid_t *aux = pid;
|
|
pid = pid->next;
|
|
vPortFree(aux);
|
|
}
|
|
vPortFree(sem->name);
|
|
vPortFree(sem);
|
|
vPortFree(del);
|
|
|
|
counter--;
|
|
leave_region(&semLock);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
#include "video.h"
|
|
|
|
void semWait(sem_t *sem) {
|
|
enter_region(&semLock);
|
|
|
|
if (sem->value > 0) {
|
|
sem->value--;
|
|
} else {
|
|
leave_region(&semLock);
|
|
|
|
pid_t *curr = pvPortMalloc(sizeof(pid_t));
|
|
curr->pid = getPid();
|
|
curr->next = NULL;
|
|
if (sem->entering == NULL)
|
|
sem->entering = curr;
|
|
if (sem->last != NULL)
|
|
sem->last->next = curr;
|
|
sem->last = curr;
|
|
block(curr->pid);
|
|
|
|
enter_region(&semLock);
|
|
sem->value--;
|
|
}
|
|
|
|
leave_region(&semLock);
|
|
}
|
|
|
|
void semPost(sem_t *sem) {
|
|
enter_region(&semLock);
|
|
|
|
sem->value++;
|
|
|
|
if (sem->entering != NULL) {
|
|
pid_t *aux = sem->entering;
|
|
sem->entering = sem->entering->next;
|
|
if (sem->entering == NULL)
|
|
sem->last = NULL;
|
|
leave_region(&semLock);
|
|
unblockFirst(aux->pid);
|
|
vPortFree(aux);
|
|
enter_region(&semLock);
|
|
}
|
|
|
|
leave_region(&semLock);
|
|
}
|
|
|
|
char getSemaphoresData(char *out, node_t *node) {
|
|
if (node == NULL)
|
|
return EXIT_FAILURE;
|
|
|
|
char written = 0;
|
|
|
|
char flag = 0;
|
|
for (int j = 0; j < MAX_NAME_SIZE; j++) {
|
|
if (!flag && node->sem->name[j] == 0)
|
|
flag = 1;
|
|
else if (flag)
|
|
out += addSpaces(out, 1);
|
|
else
|
|
*out++ = node->sem->name[j];
|
|
}
|
|
written += MAX_NAME_SIZE;
|
|
|
|
out += addSpaces(out, 2);
|
|
written += 2;
|
|
|
|
char buffer[10];
|
|
char copied = strcpy(out, itoa(node->sem->value, buffer, 10, 2));
|
|
out += copied;
|
|
out += addSpaces(out, MAX_ATTR_SIZE - copied);
|
|
written += MAX_ATTR_SIZE;
|
|
out += addSpaces(out, 2);
|
|
written += 2;
|
|
|
|
pid_t *aux_pid = node->sem->entering;
|
|
|
|
while (aux_pid != NULL) {
|
|
copied = strcpy(out, itoa(aux_pid->pid, buffer, 10, 10));
|
|
aux_pid = aux_pid->next;
|
|
copied += addSpaces(out, 1);
|
|
out += copied;
|
|
written += copied;
|
|
}
|
|
return written;
|
|
}
|
|
|
|
char *getEntering(sem_t *sem) {
|
|
char *ans = pvPortMalloc(sizeof(pid_t * ));
|
|
pid_t *aux = sem->entering;
|
|
char buffer[MAX_PID];
|
|
while (aux != NULL) {
|
|
strcpy(ans, itoa(aux->pid, buffer, 10, 3));
|
|
aux = aux->next;
|
|
if (aux != NULL)
|
|
strcpy(ans, " ");
|
|
}
|
|
return ans;
|
|
}
|
|
|
|
char *getSems() {
|
|
char *ans = pvPortMalloc(1 + counter * SEM_DATA_MAX_SIZE);
|
|
char *ret = ans;
|
|
|
|
char *info = "name value pidsWaiting\n";
|
|
ans += strcpy(ans, info);
|
|
|
|
node_t *aux = firstSem;
|
|
while (aux != NULL) {
|
|
char writtenChars = getSemaphoresData(ans, aux);
|
|
if (writtenChars == EXIT_FAILURE)
|
|
return NULL;
|
|
ans += writtenChars - 1;
|
|
*ans++ = '\n';
|
|
|
|
aux = aux->next;
|
|
|
|
}
|
|
*--ans = 0;
|
|
|
|
return ret;
|
|
}
|