From 58a944ee6ea20ec9ed4a704ce49038b8c263e9e7 Mon Sep 17 00:00:00 2001 From: Curle Date: Mon, 31 Aug 2020 21:44:54 +0100 Subject: [PATCH] Add startings of new kernel-side library Lainlib is libk. It is separate from Helix, which will become the 3D engine common to the kernel and the userspace. --- chroma/inc/lainlib/compression/lzg.h | 327 ++++++++++++++++++++++++++ chroma/inc/lainlib/lainlib.h | 25 ++ chroma/inc/lainlib/list/list.h | 34 +++ chroma/inc/lainlib/mutex/spinlock.h | 22 ++ chroma/inc/lainlib/mutex/ticketlock.h | 32 +++ chroma/inc/lainlib/vector/vector.h | 30 +++ chroma/lainlib/compression/lzgmini.c | 190 +++++++++++++++ chroma/lainlib/list/basic_list.c | 27 +++ chroma/lainlib/mutex/ticketlock.c | 21 ++ chroma/lainlib/vector.c | 68 ++++++ 10 files changed, 776 insertions(+) create mode 100644 chroma/inc/lainlib/compression/lzg.h create mode 100644 chroma/inc/lainlib/lainlib.h create mode 100644 chroma/inc/lainlib/list/list.h create mode 100644 chroma/inc/lainlib/mutex/spinlock.h create mode 100644 chroma/inc/lainlib/mutex/ticketlock.h create mode 100644 chroma/inc/lainlib/vector/vector.h create mode 100644 chroma/lainlib/compression/lzgmini.c create mode 100644 chroma/lainlib/list/basic_list.c create mode 100644 chroma/lainlib/mutex/ticketlock.c create mode 100644 chroma/lainlib/vector.c diff --git a/chroma/inc/lainlib/compression/lzg.h b/chroma/inc/lainlib/compression/lzg.h new file mode 100644 index 0000000..89e139d --- /dev/null +++ b/chroma/inc/lainlib/compression/lzg.h @@ -0,0 +1,327 @@ +/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; -*- */ + +/* +* This file is part of liblzg. +* +* Copyright (c) 2010-2018 Marcus Geelnard +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would +* be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not +* be misrepresented as being the original software. +* +* 3. This notice may not be removed or altered from any source +* distribution. +*/ + +#ifndef _LIBLZG_H_ +#define _LIBLZG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define LZG_VERSION "1.0.10" /**< @brief LZG library version string */ +#define LZG_VERNUM 0x0100000a /**< @brief LZG library version number (strictly + incremental) */ +#define LZG_VER_MAJOR 1 /**< @brief LZG library major version */ +#define LZG_VER_MINOR 0 /**< @brief LZG library minor version */ +#define LZG_VER_REVISION 10 /**< @brief LZG library revision */ + +/** +* @file +* @mainpage +* +* @section intro_sec Introduction +* +* liblzg is a minimal implementation of an LZ77 class compression library. The +* main characteristic of the library is that the decoding routine is very +* simple, fast and requires no extra memory (except for the encoded and decoded +* data buffers). +* +* @section funcs_sec Functions +* +* @li LZG_MaxEncodedSize() - Determine the maximum size of the encoded data for +* a given uncompressed buffer (worst case). +* @li LZG_InitEncoderConfig() - Set default encoder configuration. +* @li LZG_Encode() - Encode uncompressed data as LZG coded data. +* @li LZG_EncodeFull() - Same as LZG_Encode(), but using custom memory +* allocation. +* @li LZG_WorkMemSize() - Determine the amount of memory required for encoding +* (useful for LZG_EncodeFull()). +* +* @li LZG_DecodedSize() - Determine the size of the decoded data for a given +* LZG coded buffer. +* @li LZG_Decode() - Decode LZG coded data. +* +* @li LZG_Version() - Get the version of the LZG library. +* @li LZG_VersionString() - Get the version of the LZG library. +* +* @section compr_sec Compression +* Here is a simple example of compressing an uncompressed data buffer (given +* as buf/bufSize). +* +* @code +* unsigned char *encBuf; +* lzg_uint32_t encSize, maxEncSize; +* +* // Determine maximum size of compressed data +* maxEncSize = LZG_MaxEncodedSize(bufSize); +* +* // Allocate memory for the compressed data +* encBuf = (unsigned char*) malloc(maxEncSize); +* if (encBuf) +* { +* // Compress +* encSize = LZG_Encode(buf, bufSize, encBuf, maxEncSize, NULL); +* if (encSize) +* { +* // Compressed data is now in encBuf, use it... +* // ... +* } +* else +* fprintf(stderr, "Compression failed!\n"); +* +* // Free memory when we're done with the compressed data +* free(encBuf); +* } +* else +* fprintf(stderr, "Out of memory!\n"); +* @endcode +* +* @section decompr_sec Decompression +* Here is a simple example of decompressing a compressed data buffer (given +* as buf/bufSize). +* +* @code +* unsigned char *decBuf; +* lzg_uint32_t decSize; +* +* // Determine size of decompressed data +* decSize = LZG_DecodedSize(buf, bufSize); +* if (decSize) +* { +* // Allocate memory for the decompressed data +* decBuf = (unsigned char*) malloc(decSize); +* if (decBuf) +* { +* // Decompress +* decSize = LZG_Decode(buf, bufSize, decBuf, decSize); +* if (decSize) +* { +* // Uncompressed data is now in decBuf, use it... +* // ... +* } +* else +* printf("Decompression failed (bad data)!\n"); +* +* // Free memory when we're done with the decompressed data +* free(decBuf); +* } +* else +* printf("Out of memory!\n"); +* } +* else +* printf("Bad input data!\n"); +* @endcode +*/ + +/* Basic types */ +typedef int lzg_bool_t; /**< @brief Boolean (@ref LZG_TRUE/@ref LZG_FALSE) */ +typedef int lzg_int32_t; /**< @brief Signed 32-bit integer */ +typedef unsigned int lzg_uint32_t; /**< @brief Unsigned 32-bit integer */ + +#define LZG_FALSE 0 /**< @brief Boolean FALSE (see @ref lzg_bool_t) */ +#define LZG_TRUE 1 /**< @brief Boolean TRUE (see @ref lzg_bool_t) */ + +/* Compression levels */ +#define LZG_LEVEL_1 1 /**< @brief Lowest/fastest compression level */ +#define LZG_LEVEL_2 2 /**< @brief Compression level 2 */ +#define LZG_LEVEL_3 3 /**< @brief Compression level 3 */ +#define LZG_LEVEL_4 4 /**< @brief Compression level 4 */ +#define LZG_LEVEL_5 5 /**< @brief Medium compression level */ +#define LZG_LEVEL_6 6 /**< @brief Compression level 6 */ +#define LZG_LEVEL_7 7 /**< @brief Compression level 7 */ +#define LZG_LEVEL_8 8 /**< @brief Compression level 8 */ +#define LZG_LEVEL_9 9 /**< @brief Best/slowest compression level */ + +/** @brief Default compression level */ +#define LZG_LEVEL_DEFAULT LZG_LEVEL_5 + +/** +* Progress callback function. +* @param[in] progress The current progress (0-100). +* @param[in] userdata User supplied data pointer. +*/ +typedef void (*LZGPROGRESSFUN)(lzg_int32_t progress, void *userdata); + +/** @brief LZG compression configuration parameters. +* +* This structure is used for passing configuration options to the LZG_Encode() +* function. Initialize this structure to default values with +* @ref LZG_InitEncoderConfig(). +*/ +typedef struct { + /** @brief Compression level (1-9). + + For convenience, you can use the predefined constants + @ref LZG_LEVEL_1 (fast) to @ref LZG_LEVEL_9 (slow), or + @ref LZG_LEVEL_DEFAULT. + + Default value: LZG_LEVEL_DEFAULT */ + lzg_int32_t level; + + /** @brief Use fast method (LZG_FALSE or LZG_TRUE). + + Boolean flag that specifies whether or not to use a faster encoding + acceleration data structure, which requires more memory. When using the + fast method, the compression ratio is usually slightly improved. + + Default value: LZG_TRUE */ + lzg_bool_t fast; + + /** @brief Encoding progress callback function. + + This function will be called during compression to report progress + back to the caller (set this to NULL to disable progress + callback). + + Default value: NULL */ + LZGPROGRESSFUN progressfun; + + /** @brief User data pointer for the progress callback function. + + A user defined data pointer that can point to anything that the + progress callback function may need, such as an object reference + (this can set to NULL if the callback function does not need it). + + Default value: NULL */ + void *userdata; +} lzg_encoder_config_t; + + +/** +* Determine the maximum size of the encoded data for a given uncompressed +* buffer. +* @param[in] insize Size of the uncompressed buffer (number of bytes). +* @return Worst case (maximum) size of the encoded data. +*/ +lzg_uint32_t LZG_MaxEncodedSize(lzg_uint32_t insize); + +/** +* Initialize an encoder configuration object. +* @param[out] config Configuration object. +*/ +void LZG_InitEncoderConfig(lzg_encoder_config_t *config); + +/** +* Determine the amount of memory required for encoding. +* @param[in] config Compression configuration (if set to NULL, default encoder +* configuration parameters are used). +* @retrun The size of the buffer required. +*/ +lzg_uint32_t LZG_WorkMemSize(lzg_encoder_config_t *config); + +/** +* Encode uncompressed data using the LZG coder (i.e. compress the data). +* @param[in] in Input (uncompressed) buffer. +* @param[in] insize Size of the input buffer (number of bytes). +* @param[out] out Output (compressed) buffer. +* @param[in] outsize Size of the output buffer (number of bytes). +* @param[in] config Compression configuration (if set to NULL, default encoder +* configuration parameters are used). +* @return The size of the encoded data, or zero if the function failed +* (e.g. if the end of the output buffer was reached before the +* entire input buffer was encoded). +* @note For the slow method (config->fast = 0), the memory requirement during +* compression is 136 KB (LZG_LEVEL_1) to 2 MB (LZG_LEVEL_9). For the fast +* method (config->fast = 1), the memory requirement is 64 MB (LZG_LEVEL_1) to +* 66 MB (LZG_LEVEL_9). Also note that these figures are doubled on 64-bit +* systems. +*/ +lzg_uint32_t LZG_Encode(const unsigned char *in, lzg_uint32_t insize, + unsigned char *out, lzg_uint32_t outsize, + lzg_encoder_config_t *config); + +/** +* Encode uncompressed data using the LZG coder (i.e. compress the data). +* @param[in] in Input (uncompressed) buffer. +* @param[in] insize Size of the input buffer (number of bytes). +* @param[out] out Output (compressed) buffer. +* @param[in] outsize Size of the output buffer (number of bytes). +* @param[in] config Compression configuration (if set to NULL, default encoder +* configuration parameters are used). +* @param[in] workmem Buffer to be used for compression, or NULL. See +* @ref LZG_WorkMemSize. +* @return The size of the encoded data, or zero if the function failed +* (e.g. if the end of the output buffer was reached before the +* entire input buffer was encoded). +* @note For the slow method (config->fast = 0), the memory requirement during +* compression is 136 KB (LZG_LEVEL_1) to 2 MB (LZG_LEVEL_9). For the fast +* method (config->fast = 1), the memory requirement is 64 MB (LZG_LEVEL_1) to +* 66 MB (LZG_LEVEL_9). Also note that these figures are doubled on 64-bit +* systems. +*/ +lzg_uint32_t LZG_EncodeFull(const unsigned char *in, lzg_uint32_t insize, + unsigned char *out, lzg_uint32_t outsize, + lzg_encoder_config_t *config, + void *workmem); + +/** +* Determine the size of the decoded data for a given LZG coded buffer. +* @param[in] in Input (compressed) buffer. +* @param[in] insize Size of the input buffer (number of bytes). This does +* not have to be the size of the entire compressed data, but +* it has to be at least 7 bytes (the first few bytes of the +* header, including the decompression size). +* @return The size of the decoded data, or zero if the function failed +* (e.g. if the magic header ID could not be found). +*/ +lzg_uint32_t LZG_DecodedSize(const unsigned char *in, lzg_uint32_t insize); + + +/** +* Decode LZG coded data. +* @param[in] in Input (compressed) buffer. +* @param[in] insize Size of the input buffer (number of bytes). +* @param[out] out Output (uncompressed) buffer. +* @param[in] outsize Size of the output buffer (number of bytes). +* @return The size of the decoded data, or zero if the function failed +* (e.g. if the end of the output buffer was reached before the +* entire input buffer was decoded). +*/ +lzg_uint32_t LZG_Decode(const unsigned char *in, lzg_uint32_t insize, + unsigned char *out, lzg_uint32_t outsize); + + +/** +* Get the version of the LZG library. +* @return The version of the LZG library, on the same format as +* @ref LZG_VERNUM. +*/ +lzg_uint32_t LZG_Version(void); + + +/** +* Get the version string of the LZG library. +* @return The version of the LZG library, on the same format as +* @ref LZG_VERSION. +*/ +const char* LZG_VersionString(void); + +#ifdef __cplusplus +} +#endif + +#endif // _LIBLZG_H_ diff --git a/chroma/inc/lainlib/lainlib.h b/chroma/inc/lainlib/lainlib.h new file mode 100644 index 0000000..1b717d2 --- /dev/null +++ b/chroma/inc/lainlib/lainlib.h @@ -0,0 +1,25 @@ + +#pragma once + +/************************ + *** Team Kitty, 2020 *** + *** Chroma *** + ***********************/ + + +/* Defines all of the temporary library functions. + * All of this must be moved into the Chroma stdlib. + * They exist here as guidance, and as utility for the kernel itself. + * If need be, they can also be moved into a trimmed-down "kernel libc" or "libk". + */ + + + +#include + +#include + +#include +#include + +#include diff --git a/chroma/inc/lainlib/list/list.h b/chroma/inc/lainlib/list/list.h new file mode 100644 index 0000000..697e32c --- /dev/null +++ b/chroma/inc/lainlib/list/list.h @@ -0,0 +1,34 @@ +#include + +typedef struct list_entry { + struct list_entry* Previous; + struct list_entry* Next; +} list_entry_t; + +#define UNSAFE_CAST(ptr, type, member) \ + ((type*)((char*)(ptr) - (char*)offsetof(type, member))) + +#define LISTNEW(var) \ + ((list_entry_t){ 0, 0 }) + +void ListAdd(list_entry_t* Head, list_entry_t* New); + +void ListEmplaceBack(list_entry_t* Head, list_entry_t* Tail); + +void ListRemove(list_entry_t* List); + +bool ListIsEmpty(list_entry_t* Head); + +#define LISTNEXT(current, member) \ + UNSAFE_CAST((current)->member.next, typeof(*(current)), member); + +#define LISTPREV(current, member) \ + UNSAFE_CAST((current)->member.prev, typeof(*(curent)), member) + +#define LISTFOREACH(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +#define LISTFOREACHENTRY(pos, head, member) \ + for(pos = UNSAFE_CAST((head)->next, typeof(*(pos)), member); &pos->member != (head); pos = LISTNEXT(pos, member)) + +#define LASTENTRY 0 \ No newline at end of file diff --git a/chroma/inc/lainlib/mutex/spinlock.h b/chroma/inc/lainlib/mutex/spinlock.h new file mode 100644 index 0000000..5c8f0d1 --- /dev/null +++ b/chroma/inc/lainlib/mutex/spinlock.h @@ -0,0 +1,22 @@ +#pragma once + +/************************ + *** Team Kitty, 2020 *** + *** Chroma *** + ***********************/ + + +typedef volatile int spinlock_t; + +/* A set of macros that acquire and release a mutex spinlock. */ +//TODO: this *needs* to be moved to a kernel header. + +#define SPINLOCK(name) \ + while( !__sync_bool_compare_and_swap(name, 0, 1)); \ + __sync_synchronize(); + + +#define SPUNLOCK(name) \ + __sync_synchronize(); \ + name = 0; + diff --git a/chroma/inc/lainlib/mutex/ticketlock.h b/chroma/inc/lainlib/mutex/ticketlock.h new file mode 100644 index 0000000..02720fe --- /dev/null +++ b/chroma/inc/lainlib/mutex/ticketlock.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include + +/************************ + *** Team Kitty, 2020 *** + *** Chroma *** + ***********************/ + +/* This file provides a simple implementation of a ticket-based locking system. + * You should probably prefer Spinlock over Ticketlock. + * + * Create a new lock with NEW_TICKETLOCK(), + * lock a resource with TicketLock(). + * + * Use TicketUnlock() to free the resource after you are done. + * + */ + +typedef struct { + atomic_size_t NowServing; + atomic_size_t NextTicket; +} ticketlock_t; + +#define NEW_TICKETLOCK() (ticketlock_t{0}) + +void TicketLock(ticketlock_t* Lock); + +bool TicketAttemptLock(ticketlock_t* Lock); + +void TicketUnlock(ticketlock_t* Lock); + diff --git a/chroma/inc/lainlib/vector/vector.h b/chroma/inc/lainlib/vector/vector.h new file mode 100644 index 0000000..ad76e02 --- /dev/null +++ b/chroma/inc/lainlib/vector/vector.h @@ -0,0 +1,30 @@ +/************************ + *** Team Kitty, 2020 *** + *** Chroma *** + ***********************/ + + +#pragma once + +#include +#include +#include + +struct vector_t { + void** items; + size_t n; + + spinlock_t vector_lock; +}; + +int VectorRemoveItem(struct vector_t* vec, void* item); + +int VectorRemove(struct vector_t* vec, size_t index); + +void* VectorGet(struct vector_t* vec, size_t index); + +int VectorInsert(struct vector_t* vec, void* item, size_t index); + +int VectorAppend(struct vector_t* vec, void* item); + +int VectorDestroy(struct vector_t* vec); \ No newline at end of file diff --git a/chroma/lainlib/compression/lzgmini.c b/chroma/lainlib/compression/lzgmini.c new file mode 100644 index 0000000..c00d401 --- /dev/null +++ b/chroma/lainlib/compression/lzgmini.c @@ -0,0 +1,190 @@ +/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; -*- */ + +/* +* This file is part of liblzg. +* +* Copyright (c) 2010 Marcus Geelnard +* +* This software is provided 'as-is', without any express or implied +* warranty. In no event will the authors be held liable for any damages +* arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, +* including commercial applications, and to alter it and redistribute it +* freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not +* claim that you wrote the original software. If you use this software +* in a product, an acknowledgment in the product documentation would +* be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not +* be misrepresented as being the original software. +* +* 3. This notice may not be removed or altered from any source +* distribution. +*/ + +#include + +/*-- PRIVATE -----------------------------------------------------------------*/ + +/* Internal definitions */ +#define LZG_HEADER_SIZE 16 +#define LZG_METHOD_COPY 0 +#define LZG_METHOD_LZG1 1 + +/* Endian and alignment independent reader for 32-bit integers */ +#define _LZG_GetUINT32(in, offs) \ + ((((lzg_uint32_t)in[offs]) << 24) | \ + (((lzg_uint32_t)in[offs+1]) << 16) | \ + (((lzg_uint32_t)in[offs+2]) << 8) | \ + ((lzg_uint32_t)in[offs+3])) + +/* Calculate the checksum */ +static lzg_uint32_t _LZG_CalcChecksum(const unsigned char *data, lzg_uint32_t size) +{ + unsigned short a = 1, b = 0; + unsigned char *end = (unsigned char *)data + size; + while (data != end) + { + a += *data++; + b += a; + } + return (((lzg_uint32_t)b) << 16) | a; +} + +/* LUT for decoding the copy length parameter */ +static const unsigned char _LZG_LENGTH_DECODE_LUT[32] = { + 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,35,48,72,128 +}; + + +/*-- PUBLIC ------------------------------------------------------------------*/ + +lzg_uint32_t LZG_DecodedSize(const unsigned char *in, lzg_uint32_t insize) +{ + /* Check header */ + if ((insize < 7) || (in[0] != 'L') || (in[1] != 'Z') || (in[2] != 'G')) + return 0; + + /* Get output buffer size */ + return _LZG_GetUINT32(in, 3); +} + +lzg_uint32_t LZG_Decode(const unsigned char *in, lzg_uint32_t insize, + unsigned char *out, lzg_uint32_t outsize) +{ + unsigned char *src, *inEnd, *dst, *outEnd, *copy, symbol, b, b2; + unsigned char m1, m2, m3, m4, method; + lzg_uint32_t i, length, offset, encodedSize, decodedSize, checksum; + + /* Check magic ID */ + if ((insize < LZG_HEADER_SIZE) || (in[0] != 'L') || (in[1] != 'Z') || (in[2] != 'G')) + return 0; + + /* Get header data */ + decodedSize = _LZG_GetUINT32(in, 3); + encodedSize = _LZG_GetUINT32(in, 7); + checksum = _LZG_GetUINT32(in, 11); + + /* Check sizes */ + if ((outsize < decodedSize) || (encodedSize != (insize - LZG_HEADER_SIZE))) + return 0; + + /* Check checksum */ + if (_LZG_CalcChecksum(&in[LZG_HEADER_SIZE], encodedSize) != checksum) + return 0; + + /* Initialize the byte streams */ + src = (unsigned char *)in + LZG_HEADER_SIZE;; + inEnd = ((unsigned char *)in) + insize; + dst = out; + outEnd = out + outsize; + + /* Check which method to use */ + method = in[15]; + if (method == LZG_METHOD_LZG1) + { + if (!((src + 4) <= inEnd)) return 0; + m1 = *src++; m2 = *src++; m3 = *src++; m4 = *src++; + + /* Main decompression loop */ + while (src < inEnd) + { + symbol = *src++; + + if ((symbol != m1) && (symbol != m2) && (symbol != m3) && (symbol != m4)) + { + /* Literal copy */ + if (!(dst < outEnd)) return 0; + *dst++ = symbol; + } + else + { + /* Decode offset / length parameters */ + if (!(src < inEnd)) return 0; + if ((b = *src++)) + { + if (symbol == m1) + { + /* Distant copy */ + if (!((src + 2) <= inEnd)) return 0; + length = _LZG_LENGTH_DECODE_LUT[b & 0x1f]; + b2 = *src++; + offset = (((unsigned int)(b & 0xe0)) << 11) | + (((unsigned int)b2) << 8) | + (*src++); + offset += 2056; + } + else if (symbol == m2) + { + /* Medium copy */ + if (!(src < inEnd)) return 0; + length = _LZG_LENGTH_DECODE_LUT[b & 0x1f]; + b2 = *src++; + offset = (((unsigned int)(b & 0xe0)) << 3) | b2; + offset += 8; + } + else if (symbol == m3) + { + /* Short copy */ + length = (b >> 6) + 3; + offset = (b & 0x3f) + 8; + } + else + { + /* Near copy (including RLE) */ + length = _LZG_LENGTH_DECODE_LUT[b & 0x1f]; + offset = (b >> 5) + 1; + } + + /* Copy the corresponding data from the history window */ + copy = dst - offset; + if (!((copy >= out) && ((dst + length) <= outEnd))) return 0; + for (i = 0; i < length; ++i) + *dst++ = *copy++; + } + else + { + /* Literal copy (single occurance of a marker symbol) */ + if (!(dst < outEnd)) return 0; + *dst++ = symbol; + } + } + } + } + else if (method == LZG_METHOD_COPY) + { + /* Plain copy */ + while ((src < inEnd) && (dst < outEnd)) + *dst++ = *src++; + } + + /* All OK? */ + if ((unsigned int)(dst - out) != decodedSize) + return 0; + else + return decodedSize; +} diff --git a/chroma/lainlib/list/basic_list.c b/chroma/lainlib/list/basic_list.c new file mode 100644 index 0000000..b070140 --- /dev/null +++ b/chroma/lainlib/list/basic_list.c @@ -0,0 +1,27 @@ +#include + +void ListAdd(list_entry_t* Head, list_entry_t* New) { + New->Next = Head->Next; + New->Previous = Head; + New->Next->Previous = New; + Head->Next = New; +} + +void ListEmplaceBack(list_entry_t* Head, list_entry_t* New) { + New->Next = Head; + New->Previous = Head->Previous; + New->Previous->Next = New; + Head->Previous = New; +} + +void ListRemove(list_entry_t* Entry) { + Entry->Next->Previous = Entry->Previous; + Entry->Previous->Next = Entry->Next; + + Entry->Previous = (void*)0xDEADull; + Entry->Next = (void*)0xBEEFull; +} + +bool ListIsEmpty(list_entry_t* Head) { + return Head->Next == Head; +} \ No newline at end of file diff --git a/chroma/lainlib/mutex/ticketlock.c b/chroma/lainlib/mutex/ticketlock.c new file mode 100644 index 0000000..6d73794 --- /dev/null +++ b/chroma/lainlib/mutex/ticketlock.c @@ -0,0 +1,21 @@ +#include +#include + +void TicketLock(ticketlock_t* Lock) { + size_t Ticket = atomic_fetch_add_explicit(&Lock->NextTicket, 1, memory_order_relaxed); + + while(atomic_load_explicit(&Lock->NowServing, memory_order_acquire) != Ticket) { + PAUSE; + } +} + +bool TicketAttemptLock(ticketlock_t* Lock) { + size_t Ticket = atomic_load_explicit(&Lock->NowServing, memory_order_relaxed); + + return atomic_compare_exchange_strong_explicit(&Lock->NowServing, &Ticket, Ticket + 1, memory_order_acquire, memory_order_relaxed); +} + +void TicketUnlock(ticketlock_t* Lock) { + size_t NextTicket = atomic_load_explicit(&Lock->NowServing, memory_order_relaxed) + 1; + atomic_store_explicit(&Lock->NowServing, NextTicket, memory_order_release); +} \ No newline at end of file diff --git a/chroma/lainlib/vector.c b/chroma/lainlib/vector.c new file mode 100644 index 0000000..89919b8 --- /dev/null +++ b/chroma/lainlib/vector.c @@ -0,0 +1,68 @@ +#include + +/************************ + *** Team Kitty, 2020 *** + *** Chroma *** + ***********************/ + +/* This file provides a Chroma implementation of std::vector, a C++ standard library class. + * It has a lot of work left to be done, but it's usable for its intended function (Graphics) + */ + +int VectorRemoveItem(struct vector_t* vec, void* item) { + //TODO + return -1; + +} + +int VectorRemove(struct vector_t* vec, size_t index) { + + if (!vec) return 0; + + //TODO: Vector spinlock + // AcqSpinlock(&vec->lock); + + if((index + 1) > vec->n) return 0; + + vec->items[index] = NULL; + + for (int i = 0; i < vec->n; i++) { + vec->items[i] = vec->items[i + 1]; + } + + //TODO: vector reallocate + // realloc(vec->items, vec->n - 1); + + vec->n--; + + // ReleaseSpinlock(&vec->lock); + + return 1; + +} + +void* VectorGet(struct vector_t* vec, size_t index) { + + if(!vec) return 0; + + //TODO: Vector spinlock + // AcqSpinlock(&vec->lock); + + if((index + 1) > vec->n) return NULL; + + // ReleaseSpinlock(&vec->lock); + return vec->items[index]; + +} + +int VectorInsert(struct vector_t* vec, void* item, size_t index) { + +} + +int VectorAppend(struct vector_t* vec, void* item) { + +} + +int VectorDestroy(struct vector_t* vec) { + +} \ No newline at end of file