Initial commit
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
out
|
||||||
|
.ccls-cache
|
||||||
|
.vscode
|
||||||
|
compile_commands.json
|
||||||
97
Makefile
Normal file
97
Makefile
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
BUILD_DIR=out
|
||||||
|
SRC_DIR=src
|
||||||
|
INC_DIR=inc
|
||||||
|
CC=gcc
|
||||||
|
AR=ar
|
||||||
|
OBJDUMP=objdump
|
||||||
|
LIBS=
|
||||||
|
LIBS_HEADERS=deps/
|
||||||
|
STANDART=c23
|
||||||
|
OPTIMIZE=-Og
|
||||||
|
TARGET=ptQueue
|
||||||
|
|
||||||
|
|
||||||
|
DEFINES=#-DOPCODE_WORDSIZE=2 -DMEM_CELL_WORDS=1 -DPC_WORDSIZE=2 -DGP_REG_CELL_WORDS=1 -DIO_REG_CELL_WORDS=1
|
||||||
|
|
||||||
|
C_SOURCES=$(wildcard $(SRC_DIR)/*.c)
|
||||||
|
# C_SOURCES=$(wildcard $(SRC_DIR)/*.c)
|
||||||
|
C_HEADERS=$(wildcard $(INC_DIR)/*.h)
|
||||||
|
|
||||||
|
C_INCLUDES=-I$(INC_DIR)/ $(addprefix -I,$(LIBS_HEADERS))
|
||||||
|
|
||||||
|
C_DEFS=-D_POSIX_C_SOURCE=199309L
|
||||||
|
|
||||||
|
DISABLE_FLAGS=-Wno-unused-variable -Wno-unused-parameter -Wno-write-strings -Wno-pointer-arith
|
||||||
|
PEDANTIC_FLAGS=-pedantic -pedantic-errors $(DISABLE_FLAGS) -Wall -Wcast-align -Wcast-qual -Wconversion -Wduplicated-branches -Wduplicated-cond -Werror -Wextra -Wfloat-equal -Wlogical-op -Wpedantic -Wredundant-decls -Wsign-conversion
|
||||||
|
ANALYZER_FLAGS=-fanalyzer -fdiagnostics-show-option -fdiagnostics-color=always
|
||||||
|
LSECTIONS=-ffunction-sections -fdata-sections -Wl,--gc-sections
|
||||||
|
CFLAGS=$(C_DEFS) -g $(C_INCLUDES) $(DEFINES) $(OPTIMIZE) --std=$(STANDART) $(PEDANTIC_FLAGS) $(ANALYZER_FLAGS)
|
||||||
|
LFLAGS=$(OPTIMIZE) -g $(PEDANTIC_FLAGS) $(DEFINES) -flto -fuse-linker-plugin $(LSECTIONS) -lm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o))) $(LIBS)
|
||||||
|
vpath %.c $(sort $(dir $(C_SOURCES)))
|
||||||
|
vpath %.h $(sort $(dir $(C_HEADERS)))
|
||||||
|
|
||||||
|
# $(info SOURCES=$(C_SOURCES))
|
||||||
|
# $(info HEADERS=$(C_HEADERS))
|
||||||
|
# $(info OBJECTS=$(OBJECTS))
|
||||||
|
|
||||||
|
|
||||||
|
all: build
|
||||||
|
|
||||||
|
build: date deps Dir $(C_HEADERS) target compile_commands
|
||||||
|
|
||||||
|
rebuild: clean | build
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
target: date $(BUILD_DIR)/$(TARGET).a
|
||||||
|
|
||||||
|
|
||||||
|
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
|
||||||
|
@echo -e '\033[1;32mCC\t'$<'\t->\t'$@'\033[0m'
|
||||||
|
@$(CC) -c $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
|
||||||
|
$(BUILD_DIR)/main.elf: $(OBJECTS)
|
||||||
|
@echo -e '\033[1;32mELF\t'$(OBJECTS)'\n\t\t\t->\t'$@'\033[0m'
|
||||||
|
@$(CC) $(LFLAGS) $(OBJECTS) -o $(BUILD_DIR)/main.elf
|
||||||
|
|
||||||
|
|
||||||
|
$(BUILD_DIR)/$(TARGET).a: $(BUILD_DIR)/ptQueue.o
|
||||||
|
@echo -e '\033[1;32mAR\t'$(BUILD_DIR)/$(TARGET).o'\n\t\t\t->\t'$@'\033[0m'
|
||||||
|
@$(AR) rcs $(BUILD_DIR)/$(TARGET).a $(BUILD_DIR)/$(TARGET).o
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BuildDir:
|
||||||
|
@mkdir -p $(BUILD_DIR)
|
||||||
|
|
||||||
|
SrcDir:
|
||||||
|
@mkdir -p $(SRC_DIR)
|
||||||
|
|
||||||
|
IncDir:
|
||||||
|
@mkdir -p $(INC_DIR)
|
||||||
|
|
||||||
|
Dir: BuildDir SrcDir IncDir
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: clean deps
|
||||||
|
clean:
|
||||||
|
@rm -rf $(BUILD_DIR)/*
|
||||||
|
# @rm -f compile_commands.json
|
||||||
|
@echo -e '\033[0;31mCleaned\033[0m'
|
||||||
|
|
||||||
|
.NOTPARALLEL: date target rebuild deps
|
||||||
|
date:
|
||||||
|
@echo -e '\033[1;32m'"Starting building $(TARGET) at " | tr -d '\n'
|
||||||
|
@date
|
||||||
|
@echo -e '\033[0m'
|
||||||
|
|
||||||
|
|
||||||
|
compile_commands:
|
||||||
|
# @bear -- ./.gen_compile_commands.sh $(TARGET) $(CC) "$(CFLAGS)" "$(LFLAGS)" "$(OBJECTS)"
|
||||||
20
inc/ptQueue.h
Normal file
20
inc/ptQueue.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef __PT_QUEUE_H__
|
||||||
|
#define __PT_QUEUE_H__
|
||||||
|
|
||||||
|
typedef struct ptQueueElem {
|
||||||
|
_Atomic(struct ptQueueElem*) nextEl;
|
||||||
|
_Atomic(void*) payload;
|
||||||
|
} ptQueueElem;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
_Atomic(ptQueueElem*) head;
|
||||||
|
_Atomic(ptQueueElem*) tail;
|
||||||
|
} ptQueue;
|
||||||
|
|
||||||
|
|
||||||
|
int ptQueuePush(ptQueue* q, void* payload, char* errbuf);
|
||||||
|
ptQueue* ptQueueCreate(char* errbuf);
|
||||||
|
void ptQueueFree(ptQueue* q);
|
||||||
|
|
||||||
|
#endif //ifndef __PT_QUEUE_H__
|
||||||
203
src/main.c
Normal file
203
src/main.c
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "ptQueue.h"
|
||||||
|
|
||||||
|
|
||||||
|
void *threadMain(void *param);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void microsecond_sleep(int microseconds) {
|
||||||
|
struct timespec ts;
|
||||||
|
ts.tv_sec = microseconds / 1000000;
|
||||||
|
ts.tv_nsec = (microseconds % 1000000) * 1000;
|
||||||
|
nanosleep(&ts, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
|
||||||
|
pthread_t tid;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
|
||||||
|
char errbuf[1024];
|
||||||
|
|
||||||
|
|
||||||
|
ptQueue* qOut = ptQueueCreate(errbuf);
|
||||||
|
if(qOut == NULL)
|
||||||
|
{
|
||||||
|
printf("Failed to create out q: %s\n", errbuf);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
ptQueue* qIn = ptQueueCreate(errbuf);
|
||||||
|
if(qIn == NULL)
|
||||||
|
{
|
||||||
|
printf("Failed to create out q: %s\n", errbuf);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
ptQueue** ptArgs = malloc(sizeof(ptQueue*) * 2);
|
||||||
|
if(ptArgs == NULL)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
ptArgs[0] = qOut;
|
||||||
|
ptArgs[1] = qIn;
|
||||||
|
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
pthread_create(&tid, &attr, threadMain, ptArgs);
|
||||||
|
|
||||||
|
|
||||||
|
for(int i = 1; i < 4096; i++)
|
||||||
|
{
|
||||||
|
int* pass = malloc(sizeof(int));
|
||||||
|
if(pass == NULL)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
*pass = i;
|
||||||
|
|
||||||
|
int excode = ptQueuePush(qOut, pass, errbuf);
|
||||||
|
if(excode)
|
||||||
|
{
|
||||||
|
printf("Unable to push: %s\n", errbuf);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int* ii = malloc(sizeof(int));
|
||||||
|
if(ii == NULL)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
*ii = 0;
|
||||||
|
|
||||||
|
int excode = ptQueuePush(qOut, ii, errbuf);
|
||||||
|
if(excode)
|
||||||
|
{
|
||||||
|
printf("Unable to push 0: %s\n", errbuf);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
ptQueueElem* tailIn = qIn->tail;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
void* payload = atomic_load(&(tailIn->payload));
|
||||||
|
if(payload == NULL)
|
||||||
|
{
|
||||||
|
microsecond_sleep(100);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int* code = payload;
|
||||||
|
|
||||||
|
printf("<Done reading %d\n", *code);
|
||||||
|
|
||||||
|
|
||||||
|
int* pass = malloc(sizeof(int));
|
||||||
|
if(pass != NULL)
|
||||||
|
{
|
||||||
|
*pass = *code;
|
||||||
|
int excode = ptQueuePush(qOut, pass, errbuf);
|
||||||
|
if(excode)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*code == 0)
|
||||||
|
{
|
||||||
|
free(payload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(payload);
|
||||||
|
ptQueueElem* newTail = atomic_load(&(tailIn->nextEl));
|
||||||
|
if (newTail == NULL)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
free(tailIn);
|
||||||
|
tailIn = newTail;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_join(tid, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void *threadMain(void *param)
|
||||||
|
{
|
||||||
|
ptQueue** params = param;
|
||||||
|
ptQueue* qIn = params[0];
|
||||||
|
ptQueue* qOut = params[1];
|
||||||
|
ptQueueElem* tailIn = atomic_load(&(qIn->head));
|
||||||
|
char errbuf[1024];
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
void* payload = atomic_load(&(tailIn->payload));
|
||||||
|
if(payload == NULL)
|
||||||
|
{
|
||||||
|
microsecond_sleep(100);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int* code = payload;
|
||||||
|
|
||||||
|
printf(">Done reading %d\n", *code);
|
||||||
|
|
||||||
|
|
||||||
|
int* pass = malloc(sizeof(int));
|
||||||
|
if(pass != NULL)
|
||||||
|
{
|
||||||
|
*pass = *code;
|
||||||
|
ptQueuePush(qOut, pass, errbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*code == 0)
|
||||||
|
{
|
||||||
|
free(payload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free(payload);
|
||||||
|
ptQueueElem* newTail = atomic_load(&(tailIn->nextEl));
|
||||||
|
if (newTail == NULL)
|
||||||
|
{
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
free(tailIn);
|
||||||
|
tailIn = newTail;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 4096; i >= 0; i--)
|
||||||
|
{
|
||||||
|
int* pass = malloc(sizeof(int));
|
||||||
|
if(pass == NULL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*pass = i;
|
||||||
|
int excode = ptQueuePush(qOut, pass, errbuf);
|
||||||
|
if(excode != 0)
|
||||||
|
{
|
||||||
|
printf("failed to push: %s\n", errbuf);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_exit(0);
|
||||||
|
}
|
||||||
83
src/ptQueue.c
Normal file
83
src/ptQueue.c
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
#include <unistd.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "ptQueue.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int ptQueuePush(ptQueue* q, void* payload, char* errbuf)
|
||||||
|
{
|
||||||
|
_Atomic(ptQueueElem*) tail = atomic_load(&q->tail);
|
||||||
|
|
||||||
|
|
||||||
|
ptQueueElem* newNode = (ptQueueElem*)malloc(sizeof(ptQueue));
|
||||||
|
if(newNode == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate new node");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
newNode->payload = NULL;
|
||||||
|
newNode->nextEl = NULL;
|
||||||
|
|
||||||
|
q->tail = newNode;
|
||||||
|
|
||||||
|
ptQueueElem* oldNext = atomic_load(&tail->nextEl);
|
||||||
|
|
||||||
|
do {
|
||||||
|
tail->nextEl = newNode;
|
||||||
|
} while (!atomic_compare_exchange_weak(&tail->nextEl, &oldNext, newNode));
|
||||||
|
|
||||||
|
|
||||||
|
void* oldPayload = atomic_load(&tail->payload);
|
||||||
|
|
||||||
|
do {
|
||||||
|
tail->payload = payload;
|
||||||
|
} while (!atomic_compare_exchange_weak(&tail->payload, &oldPayload, payload));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ptQueue* ptQueueCreate(char* errbuf)
|
||||||
|
{
|
||||||
|
ptQueue* q = malloc(sizeof(ptQueue));
|
||||||
|
if(q == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate queue struct");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ptQueueElem* baseElm = malloc(sizeof(ptQueueElem));
|
||||||
|
if(baseElm == NULL)
|
||||||
|
{
|
||||||
|
sprintf(errbuf, "unable to allocate first queue elem");
|
||||||
|
free(q);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
baseElm->nextEl = NULL;
|
||||||
|
baseElm->payload = NULL;
|
||||||
|
q->head = baseElm;
|
||||||
|
q->tail = baseElm;
|
||||||
|
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ptQueueFree(ptQueue* q)
|
||||||
|
{
|
||||||
|
if(q == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ptQueueElem* head = q->head;
|
||||||
|
while(head != NULL)
|
||||||
|
{
|
||||||
|
ptQueueElem* newHead = head->nextEl;
|
||||||
|
if(head->payload != NULL)
|
||||||
|
{
|
||||||
|
free(head->payload);
|
||||||
|
}
|
||||||
|
free(head);
|
||||||
|
head = newHead;
|
||||||
|
}
|
||||||
|
free(q);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user