summary refs log tree commit diff stats
path: root/Makefile
blob: 1319c6f0b727254d582990011684bcfde9de6b0e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# Install to /usr/local unless otherwise specified, such as `make
# PREFIX=/app`.
PREFIX?=/usr/local

INSTALL?=install
INSTALL_PROGRAM=$(INSTALL) -Dm 755
INSTALL_DATA=$(INSTALL) -Dm 644

bindir=$(DESTDIR)$(PREFIX)/bin
sharedir=$(DESTDIR)$(PREFIX)/share

# OpenBSD doesn't index /usr/local/share/man by default so
# /usr/local/man will be used.
platform_id != uname -s
mandir != if [ $(platform_id) = OpenBSD ]; then \
    echo $(DESTDIR)$(PREFIX)/man; \
else \
    echo $(DESTDIR)$(PREFIX)/share/man; \
fi

help:
	@echo "targets:"
	@awk -F '#' '/^[a-zA-Z0-9_-]+:.*?#/ { print $0 }' $(MAKEFILE_LIST) \
	| sed -n 's/^\(.*\): \(.*\)#\(.*\)/  \1|-\3/p' \
	| column -t  -s '|'

install: draco.pl draco.1 README.org # system install
	$(INSTALL_PROGRAM) draco.pl $(bindir)/draco

	$(INSTALL_DATA) draco.1 $(mandir)/man1/draco.1
	$(INSTALL_DATA) README.org $(sharedir)/doc/draco/README.org


uninstall: # system uninstall
	rm -f $(bindir)/draco
	rm -f $(mandir)/man1/draco.1
	rm -fr $(sharedir)/doc/draco/

.PHONY: install uninstall help
} /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
#include "list.h"
#include "pipe.h"
#include "fs.h"
#include "alloc.h"
#include "fifobuffer.h"

static List* gPipeList = NULL;

static FileSystemNode* gPipesRoot = NULL;

static FileSystemDirent gDirent;

typedef struct Pipe {
    char name[32];
    FifoBuffer* buffer;
    FileSystemNode* fsNode;
    List* accessingThreads;
} Pipe;

static BOOL pipes_open(File *file, uint32 flags);
static FileSystemDirent *pipes_readdir(FileSystemNode *node, uint32 index);
static FileSystemNode *pipes_finddir(FileSystemNode *node, char *name);

void initializePipes() {
    gPipeList = List_Create();

    gPipesRoot = getFileSystemNode("/system/pipes");

    if (NULL == gPipesRoot) {
        WARNING("/system/pipes not found!!");
    }
    else {
        gPipesRoot->open = pipes_open;
        gPipesRoot->finddir = pipes_finddir;
        gPipesRoot->readdir = pipes_readdir;
    }
}

static BOOL pipes_open(File *file, uint32 flags) {
    return TRUE;
}

static FileSystemDirent *pipes_readdir(FileSystemNode *node, uint32 index) {
    int counter = 0;

    List_Foreach (n, gPipeList) {
        Pipe* p = (Pipe*)n->data;

        if (counter == index) {
            strcpy(gDirent.name, p->name);
            gDirent.fileType = FT_Pipe;

            return &gDirent;
        }
        ++counter;
    }

    return NULL;
}

static FileSystemNode *pipes_finddir(FileSystemNode *node, char *name) {
    List_Foreach (n, gPipeList) {
        Pipe* p = (Pipe*)n->data;

        if (strcmp(name, p->name) == 0) {
            return p->fsNode;
        }
    }

    return NULL;
}

static BOOL pipe_open(File *file, uint32 flags) {
    beginCriticalSection();

    Pipe* pipe = file->node->privateNodeData;

    List_Append(pipe->accessingThreads, file->thread);

    endCriticalSection();

    return TRUE;
}

static void pipe_close(File *file) {
    beginCriticalSection();

    Pipe* pipe = file->node->privateNodeData;

    List_RemoveFirstOccurrence(pipe->accessingThreads, file->thread);

    endCriticalSection();
}

static void blockAccessingThreads(Pipe* pipe) {
    disableInterrupts();

    List_Foreach (n, pipe->accessingThreads) {
        Thread* reader = n->data;

        reader->state = TS_WAITIO;

        reader->state_privateData = pipe;
    }

    enableInterrupts();

    halt();
}

static void wakeupAccessingThreads(Pipe* pipe) {
    beginCriticalSection();

    List_Foreach (n, pipe->accessingThreads) {
        Thread* reader = n->data;

        if (reader->state == TS_WAITIO) {
            if (reader->state_privateData == pipe) {
                reader->state = TS_RUN;
            }
        }
    }

    endCriticalSection();
}

static int32 pipe_read(File *file, uint32 size, uint8 *buffer) {
    if (0 == size || NULL == buffer) {
        return -1;
    }

    Pipe* pipe = file->node->privateNodeData;

    uint32 used = 0;
    while ((used = FifoBuffer_getSize(pipe->buffer)) < size) {
        blockAccessingThreads(pipe);
    }

    disableInterrupts();

    int32 readBytes = FifoBuffer_dequeue(pipe->buffer, buffer, size);

    wakeupAccessingThreads(pipe);

    return readBytes;
}

static int32 pipe_write(File *file, uint32 size, uint8 *buffer) {
    if (0 == size || NULL == buffer) {
        return -1;
    }

    Pipe* pipe = file->node->privateNodeData;

    uint32 free = 0;
    while ((free = FifoBuffer_getFree(pipe->buffer)) < size) {
        blockAccessingThreads(pipe);
    }

    disableInterrupts();

    int32 bytesWritten = FifoBuffer_enqueue(pipe->buffer, buffer, size);

    wakeupAccessingThreads(pipe);

    return bytesWritten;
}

BOOL createPipe(const char* name, uint32 bufferSize) {
    List_Foreach (n, gPipeList) {
        Pipe* p = (Pipe*)n->data;
        if (strcmp(name, p->name) == 0) {
            return FALSE;
        }
    }

    Pipe* pipe = (Pipe*)kmalloc(sizeof(Pipe));
    memset((uint8*)pipe, 0, sizeof(Pipe));

    strcpy(pipe->name, name);
    pipe->buffer = FifoBuffer_create(bufferSize);

    pipe->accessingThreads = List_Create();

    pipe->fsNode = (FileSystemNode*)kmalloc(sizeof(FileSystemNode));
    memset((uint8*)pipe->fsNode, 0, sizeof(FileSystemNode));
    pipe->fsNode->privateNodeData = pipe;
    pipe->fsNode->open = pipe_open;
    pipe->fsNode->close = pipe_close;
    pipe->fsNode->read = pipe_read;
    pipe->fsNode->write = pipe_write;

    List_Append(gPipeList, pipe);

    return TRUE;
}

BOOL destroyPipe(const char* name) {
    List_Foreach (n, gPipeList) {
        Pipe* p = (Pipe*)n->data;
        if (strcmp(name, p->name) == 0) {
            List_RemoveFirstOccurrence(gPipeList, p);
            FifoBuffer_destroy(p->buffer);
            List_Destroy(p->accessingThreads);
            kfree(p->fsNode);
            kfree(p);

            return TRUE;
        }
    }

    return FALSE;
}

BOOL existsPipe(const char* name) {
    List_Foreach (n, gPipeList) {
        Pipe* p = (Pipe*)n->data;
        if (strcmp(name, p->name) == 0) {
            return TRUE;
        }
    }

    return FALSE;
}