Enabling paging causes PAGE_FAULT immeditially after setting flag on cr0 - c

I'm working on own OS, it's a lot of fun but i'm stucked with paging, I had wrote simple(very simple) pagination code, but when I turn pagination on, there is page fault. Some details:
I'm using C for kernel
I'm using qemu as VM
I had own crosscompiler
I don't use any external libs
After loading and jumping into kernel code I setup interrupts and remap PIC, It's working and i reckon it's not the issue, after that I'm trying to enable paging
Here is paging.h
#ifndef PAGING_H
#define PAGING_H
#include "../cpu/types.h"
#include "../cpu/isr.h"
#define PAGE_SIZE 4096
typedef struct page{
u32 present :1;
u32 rw :1;
u32 kernel_space :1;
u32 accessed :1;
u32 dirty :1;
u32 unused :7;
u32 frame :20;
} page_t;
typedef struct page_table{
page_t pages[1024];
} page_table_t;
typedef struct page_directory{
u32 page_tables[1024];
} page_dir_t;
typedef struct page_directory_interface{
page_dir_t dir;
page_table_t* page_tables;
u32 page_dir_ph_address;
} page_dir_interface_t;
void init_paging();
void switch_page_dir(page_dir_t* new_dir);
page_t* get_page(u32 addres, page_dir_t* dir, u8 make);
void page_fault(registers_t regs);
#endif
I'm using page_t struct from some tutorial, because I reckon it's quite convinent, other parts, I've writed on my own twice, on both cases code results with PageFault. Here's paging.c:
#include "./paging.h"
#include "../util/panic.h"
#include "./memory.h"
#include "../drivers/screen.h"
page_dir_t* kernel_dir, cur_dir;
//helper function for convinient printing
void pint(u32 a){
char * tmp;
itoa(a, tmp);
kprint(tmp);
kprint("\n");
}
void init_paging(){
kernel_dir = kmalloc(sizeof(page_dir_t));
memset(kernel_dir, 0, 4096);
pint(sizeof(page_dir_t));
pint(&kernel_dir->page_tables[0]);
pint(kernel_dir);
int i;
for(i=0; i<1024; i++){ //setting up page directories for kernel
// read and write and kernel_mode and not present
kernel_dir->page_tables[i] = (u32)kmalloc(sizeof(page_table_t)) | 0x2;
}
map_page_table(kernel_dir->page_tables[0], 1, 1); //map ram to pages;
kernel_dir->page_tables[0] |= 0x3; //set as present
enable_paging();
}
void map_page_table(page_table_t* p_table, int kernel, int rw){
int i;
page_t tmp_page;
tmp_page.present = 1;
tmp_page.rw = (rw) ? 1 : 0;
tmp_page.kernel_space = (kernel) ? 1: 0;
for(i=0; i<1024; i++){
tmp_page.frame |= kmalloc(PAGE_SIZE);
p_table->pages[i] = tmp_page;
}
}
void enable_paging(){
u32 cr0_temp_value;
__asm__ __volatile__("mov %0, %%cr3":: "r"(&kernel_dir->page_tables));
__asm__ ("mov %%cr0, %0": "=r"(cr0_temp_value));
cr0_temp_value |= 0x80000000;
__asm__ __volatile__("mov %0, %%cr0":: "r"(cr0_temp_value));
}
And here is memory.c:
#include "./memory.h"
#include "../cpu/types.h"
#include "../../cathesimc/def.h"
u32 placement_addr = 0x10000;
void memcpy(char* src, char* dst, unsigned int bytes){
int i=0;
for (i=0; i< bytes; i++){
dst[i] = src[i];
}
}
void memset(u8* dest, u8 val, u32 len){
u8* tmp = (u8*)dest;
for(;len != 0; len--) *tmp++ = val;
}
//#TODO poprawic tego biedackiego malloca
u32 kmalloc_intrnl(size_t size, short int align, u32 *phys_addr){
if(align != 0 && (placement_addr & 0xFFFFF000)){
placement_addr &= 0xFFFFF000;
placement_addr += 0x1000;
}
if(phys_addr) *phys_addr = placement_addr;
u32 ret = placement_addr;
placement_addr += size;
return ret;
}
u32 kmalloc(size_t size){
return kmalloc_intrnl(size, 0, NULL);
}
u32 kmalloc_a(size_t size){
return kmalloc_intrnl(size, 1, NULL);
}
u32 kmalloc_p(size_t size, u32* phys_addr){
return kmalloc_intrnl(size, 0, phys_addr);
}
u32 kmalloc_ap(size_t size, u32* phys_addr){
return kmalloc_intrnl(size, 1, phys_addr);
}
My kernel is below 0x10000, it has about 16kb so 0x10000 is safe start of mapped space and memory from that address is definetely not used, I only set up one page table because I want to make paging barebones, and then take care about allocation and freeing, so my only goal for now is to find out what mistake I has making.
============EDIT==============
I have made intensive investigation, and I found that malloc has strange bahaviour, below are snippets of code with explaination
//as we can se from kmalloc() code above, kmalloc starts with
//placement_addr == 0x10000 when kernel starts
void init_paging(){
kernel_dir = kmalloc(sizeof(page_dir_t)); //page_dir_t has size 4096 and that is first malloc in kernel code
memset(kernel_dir, 0, 4096);
pint(sizeof(page_dir_t));
phex(sizeof(page_dir_t));
pint(&kernel_dir->page_tables[0]);
phex(&kernel_dir->page_tables[0]); //prints 0x10000 as expected
int i;
for(i=0; i<1024; i++){ //setting up page directories for kernel
// read and write and kernel_mode and not present
kernel_dir->page_tables[i] = (u32)kmalloc(sizeof(page_table_t)) | 0x2;
}
phex(kernel_dir->page_tables[0]); //0x11002 as expected
phex(kernel_dir->page_tables[1023]); //0x410002 as expected
kprint("pages\n");
map_page_table(kernel_dir->page_tables[0], 1, 1); //map ram to pages;
kernel_dir->page_tables[0] |= 0x3; //set as present
kprint("lol");
enable_paging();
}
void map_page_table(page_table_t* p_table, int kernel, int rw){
int i;
page_t tmp_page;
tmp_page.present = 1;
tmp_page.rw = (rw) ? 1 : 0;
tmp_page.kernel_space = (kernel) ? 1: 0;
//since now troubles starts this forloop below prints adresses:
// iteration0 0x11000
// iteration1 0x12000
// iteration2 0x13000
// iteration3 0x14000
// iteration4 0x15000
// iteration5 0x16000
// iteration6 0x17000
// iteration7 0x18000
for(i=0; i<8; i++){
tmp_page.frame = kmalloc(PAGE_SIZE);
phex(tmp_page.frame);
p_table->pages[i] = tmp_page;
}
}
I think that's definetly might be source of problems but I have no idea why placement_addr changes when i call another function, and why then it changes to 0x11000

Related

"Out of Memory" after adding an array in Kernel

I'm trying to trace get_page_from_freelist().
I defined a pointer of integer and initialized it with kmalloc() in mm/init_mm.c, and added some system calls to control it. But after this, I rebooted my computer and saw the "Out of Memory" error.
I reduced the array size to 4KB(512 entries), but it still shows the same error message. As far as I know, 4KB size is very small to kernel. How can I handle this problem?
My kernel version is 5.19.9 and I have 32GB physical memory. I'm using 64bit ubuntu 22.04
from mm/init-mm.c:
int trace_on;
int trace_idx;
int trace_mod;
int raw_trace[TRACE_SIZE][2];
void setup_initial_init_mm(void *start_code, void *end_code,
void *end_data, void *brk)
{
int i;
trace_on = 0;
trace_idx = 0;
trace_mod = 0;
for (i = 0; i < TRACE_SIZE; i++) {
raw_trace[I][trace_mod] = 0;
}
init_mm.start_code = (unsigned long)start_code;
init_mm.end_code = (unsigned long)end_code;
init_mm.end_data = (unsigned long)end_data;
init_mm.brk = (unsigned long)brk;
}
from include/linux/mm_types.h:
#define TRACE_SIZE 0x100
extern int trace_on;
extern int trace_idx;
extern int trace_mod;
extern int raw_trace[TRACE_SIZE][2];
from mm/page_alloc.c:
#include <linux/mm_types.h>
extern int trace_on;
extern int trace_idx;
extern int trace_mod;
extern int raw_trace[TRACE_SIZE][2];
static struct page *
get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
const struct alloc_context *ac)
{
struct zoneref *z;
struct zone *zone;
struct pglist_data *last_pgdat_dirty_limit = NULL;
bool no_fallback;
int i;
if (unlikely(!trace_on && trace_idx > 0)) {
if (unlikely(trace_idx == TRACE_SIZE))
trace_idx--;
for (i = 0; i <= trace_idx; i++) {
raw_trace[i][0] = 0;
raw_trace[i][1] = 0;
}
trace_idx = 0;
trace_mod = 0;
}
retry:
...
try_this_zone:
page = rmqueue(ac->preferred_zoneref->zone, zone, order,
gfp_mask, alloc_flags, ac->migratetype);
if (page) {
prep_new_page(page, order, gfp_mask, alloc_flags);
/*
* If this is a high-order atomic allocation then check
* if the pageblock should be reserved for the future
*/
if (unlikely(order && (alloc_flags & ALLOC_HARDER)))
reserve_highatomic_pageblock(page, zone, order);
if (unlikely(trace_on)) {
if (unlikely(trace_idx >= TRACE_SIZE)) {
if (trace_mod) trace_mod = 0;
else trace_mod = 1;
trace_idx = 0;
}
raw_trace[trace_idx++][trace_mod] = page_to_phys(page);
}
...
I think the array size or using kmalloc() is not the issue, because I've already try to reduce its size and allocate it statically.
The code above is the static allocation version of my modification.
Originally, I allocated it a buffer with kmalloc() in setup_initial_init_mm().

Can't pass array stored in .h file to C function

I am trying to implement a driver for a sensor(ST-VL53L5CX) on an AVR MCU (AVR128DB48).
The driver comes prewritten, with a few I2C functions for the user to fill in
(So the sensor can be implemented on different platforms).
The driver is made up of multiple c files. API.c, API.h, Buffers.h, Platform.c and Platform.h.
The firmware for the sensor is stored in the Buffers.h file as an array. e.g:
const uint8_t Sensor_Firmware[] = {0x05,...,0x01};
This needs to be written to the sensor.
To do this, I call a function I have written to write multiple bytes to the I2C line:
uint8_t WrMulti(VL53L5CX_Platform *p_platform,uint16_t
RegisterAdress,uint8_t *p_values,uint32_t size)
{
uint8_t count = 0;
uint32_t new_size = size + 2;
//Split Register address into 2 bytes
uint8_t temp0 = (uint8_t)((RegisterAdress & 0xFF00)>> 8);
uint8_t temp1 = (uint8_t)(RegisterAdress & 0x00FF);
//Create new array to hold Register Address and p_values
uint8_t temp_array[new_size] ;
for (int i = 0; i <new_size; i++)
{
temp_array[i] = 0;
}
//Fill temp_array with register address and p_values
temp_array[0] = temp0;
temp_array[1] = temp1;
for (int i = 2; i < (new_size); i++ )
{
temp_array[i] = p_values[count];
count++;
}
//I2C
uint8_t status = 255;
while(!I2C0_Open(p_platform->address)); // sit here until we get the bus..
I2C0_SetBuffer(temp_array,new_size);
I2C0_SetAddressNackCallback(I2C0_SetRestartWriteCallback,NULL); //NACK polling?
I2C0_MasterWrite();
while(I2C0_BUSY == I2C0_Close()); // sit here until finished.
/* This function returns 0 if OK */
status = 0;
return status;
}
This works when sending an array that is located in my main.c file.
e.g:
//buffer.h
const uint8_t Sensor_Firmware[] = {0x05,...,0x01};
//End buffer.h
.
//main.c
void main (void)
{
uint8_t I2C_address = 0x01;
uint8_t I2C_reg = 0x01;
uint32_t size = 16;
uint8_t temp_array[size];
for (int i = 0; i <size; i++)
{
temp_array[i] = Sensor_Firmware[i];
}
WrMulti(I2C_address, I2C_reg, &temp_array[0], size);
While(1)
{
;
}
}
//End main.c
It also work when passing an array from the .h file without the 'const' key word.
e.g:
//buffer.h
uint8_t Sensor_Firmware[] = {0x05,...,0x01};
//End buffer.h
.
//main.c
void main (void)
{
uint8_t I2C_address = 0x01;
uint8_t I2C_reg = 0x01;
uint32_t size = 16;
uint8_t temp_array[size];
WrMulti(I2C_address, I2C_reg, &Sensor_Firmware[0], size);
While(1)
{
;
}
}
//End main.c
It does not when I pass the 'Sensor_Firmwware[]' array (with the const key word) from the .h file to 'WrMulti'. It just ends up sending '0x00' for every byte that comes from 'Sensor_Firmware'.
Does anyone know why this is might be?
Kind regards

Why does LC_SYMTAB have invalid stroff/strsize but only for some loaded images?

I wrote the below program to iterate over all images in memory and dump their string tables.
#include <mach-o/dyld.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
uint32_t count = _dyld_image_count();
for (uint32_t i = 0 ; i < count ; i++) {
const char* imageName = _dyld_get_image_name(i);
printf("IMAGE[%u]=%s\n", i, imageName);
const struct mach_header* header = _dyld_get_image_header(i);
if (header->magic != MH_MAGIC_64)
continue;
struct mach_header_64* header64 = (struct mach_header_64*)header;
char *ptr = ((void*)header64) + sizeof(struct mach_header_64);
for (uint32_t j = 0; j < header64->ncmds; j++) {
struct load_command *lc = (struct load_command *)ptr;
ptr += lc->cmdsize;
if (lc->cmd != LC_SYMTAB)
continue;
struct symtab_command* symtab = (struct symtab_command*)lc;
printf("\t\tLC_SYMTAB.stroff=%u\n", symtab->stroff);
printf("\t\tLC_SYMTAB.strsize=%u\n", symtab->strsize);
if (symtab->strsize > 100*1024*1024) {
printf("\t\tHUH? Don't believe string table is over 100MiB in size!\n");
continue;
}
char *strtab = (((void*)header64) + symtab->stroff);
uint32_t off = 0;
while (off < symtab->strsize) {
char *e = &(strtab[off]);
if (e[0] != 0)
printf("\t\tSTR[%u]=\"%s\"\n", off, e);
off += strlen(e) + 1;
}
}
}
return 0;
}
It seems to randomly work for some images, but for others the stroff/strsize have nonsensical values:
LC_SYMTAB.stroff=1266154560
LC_SYMTAB.strsize=143767728
It seems to always be the same two magic values, but I'm not sure if this is system-dependent in some way or if other people will get the same specific values.
If I comment out the check for strsize being over 100MiB, then printing the string table segfaults.
Most images seem to have this problem, but some don't. When I run it, I get the issue for 29 images out of 38.
I can't observe any pattern as to which do and which won't. What is going on here?
If it is relevant, I am testing on macOS 10.14.6 and compiling with Apple LLVM version 10.0.1 (clang-1001.0.46.4).
As you already worked out, those are from the dyld_shared_cache. And the 0x80000000 flag is indeed documented, in the headers shipped with Xcode or any semi-recent XNU source:
#define MH_DYLIB_IN_CACHE 0x80000000 /* Only for use on dylibs. When this bit
is set, the dylib is part of the dyld
shared cache, rather than loose in
the filesystem. */
As you've also discovered, the stroff/strsize values do not yield usable results when added to the dyld_shared_cache base. That is because those are not memory offsets, but file offsets. This is true for all Mach-O's, it's just often the case that the segments of non-cached binaries have the same relative position in file and memory offsets. But this is definitely not true for the shared cache.
To translate the file offset into a memory address, you'll have to parse the segments in the shared cache header. You can find struct definitions in the dyld source.
Here's a program which prints out the contents of the string table of the dyld shared cache.
My original program in the question can be enhanced to skip dumping string table of images with MH_DYLIB_IN_CACHE set, and combined with this program to dump the shared cache string table. (All images in the shared cache share the same string table.)
#include <mach-o/dyld.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
const void* _dyld_get_shared_cache_range(size_t* cacheLen);
struct dyld_cache_header {
char magic[16];
uint32_t mappingOffset;
uint32_t mappingCount;
// Omitted remaining fields, not relevant to this task
};
struct dyld_cache_mapping_info {
uint64_t address;
uint64_t size;
uint64_t fileOffset;
uint32_t maxProt;
uint32_t initProt;
};
#ifndef MH_DYLIB_IN_CACHE
# define MH_DYLIB_IN_CACHE 0x80000000
#endif
// Finds first shared cache DYLD image. Any will do, just grab the first
const struct mach_header_64* findSharedCacheDyldImage(void) {
uint32_t count = _dyld_image_count();
for (uint32_t i = 0 ; i < count ; i++) {
const struct mach_header* header = _dyld_get_image_header(i);
if (header->magic != MH_MAGIC_64)
continue;
const struct mach_header_64* header64 = (const struct mach_header_64*)header;
if (!(header64->flags & MH_DYLIB_IN_CACHE))
continue;
return header64;
}
return NULL;
}
// Find first instance of given load command in image
const struct load_command* findFirstLoadCommand(const struct mach_header_64* header64, uint32_t cmd) {
const char *ptr = ((void*)header64) + sizeof(struct mach_header_64);
for (uint32_t j = 0; j < header64->ncmds; j++) {
const struct load_command *lc = (const struct load_command *)ptr;
ptr += lc->cmdsize;
if (lc->cmd == cmd)
return lc;
}
return NULL;
}
// Translates a shared cache file offset to a memory address
void *translateOffset(const struct dyld_cache_header *cache, uint64_t offset) {
const struct dyld_cache_mapping_info* mappings = (struct dyld_cache_mapping_info*)(((void*)cache) + cache->mappingOffset);
for (uint32_t i = 0; i < cache->mappingCount; i++) {
if (offset < mappings[i].fileOffset) continue;
if (offset >= (mappings[i].fileOffset + mappings[i].size)) continue;
return (void*)(mappings[i].address - mappings[0].address + (offset - mappings[i].fileOffset) + (uint64_t)cache);
}
return NULL;
}
int main(int argc, char** argv) {
size_t cacheLen;
const struct dyld_cache_header *cache = _dyld_get_shared_cache_range(&cacheLen);
const struct mach_header_64* sharedCacheDyldImage = findSharedCacheDyldImage();
const struct symtab_command* symtab = (const struct symtab_command*)findFirstLoadCommand(sharedCacheDyldImage,LC_SYMTAB);
const void *stringTbl = translateOffset(cache, symtab->stroff);
uint32_t off = 0;
while (off < symtab->strsize) {
const char *e = &(stringTbl[off]);
if (e[0] != 0)
printf("STR[%u]=\"%s\"\n", off, e);
off += strlen(e) + 1;
}
return 0;
}

Write to FRAM Memory Location in MSP430

I am working with MSP430 with FRAM Controller. And I Have to write a data from buffer over FRAM Location.
I have gone through bundled example of writing to FRAM.
unsigned long *FRAM_write_ptr;
unsigned long data;
#define FRAM_TEST_START 0xD000
data = 0x00010001;
void main
{
while(1)
{
data += 0x00010001;
FRAM_write_ptr = (unsigned long *)FRAM_TEST_START;
FRAMWrite(); // Endless loop
count++;
if (count > 100)
{
P1OUT ^= 0x01; // Toggle LED to show 512K bytes
count = 0; // ..have been written
data = 0x00010001;
}
}
}
void FRAMWrite(void)
{
unsigned int i=0;
for ( i= 0; i<128; i++)
{
*FRAM_write_ptr++ = data;
}
}
But When I tested example, It goes beyond the FRAM allocated section.
Is there any other method for writing on to FRAM.?

Access violation while reading in a multithreaded producer and consumer application

I have made a multi-threaded producer/consumer application which I have been struggling with for a couple of days now. The producer(s) place(s) Fibonacci numbers into a circular buffer and the consumer(s) take numbers from the buffer until the specified limit is reached.
I have protected the circular buffer with a mutex (Mutual Exclusion) which should prevent multiple threads from accessing the same data. I have also set up events which should prevent the producer(s) from overflowing the buffer, and the consumer(s) from accessing the buffer while it is empty.
While I say this, I still notice that the buffer is being accessed by consumers while it is empty. This is why I have added a break to the consumer thread (I do not quite understand why this would be necessary).
I'm also occasionally receiving "Access violation reading location" errors, which I just can't comprehend. I have noticed those occur more often up to almost always when creating more threads. I thought these might occur because the consumer was trying to read the buffer at locations that do not exist, but I have seen that this is not the case.
What might be causing my issues? Is it possible that multiple threads pass the WaitForSingleObject on the Mutex?
This is the Fibonacci.c
#include "Fibonacci.h"
#define MINIMUM 1
#define MAXIMUM 5
HANDLE eBufferNotFull;
HANDLE eBufferNotEmpty;
HANDLE fiboMutex;
HANDLE bufferMutex;
CircularBuffer *buffer;
Fibonumbers numbers;
int main(void) {
uint8_t amountOfProducers, amountOfConsumers, size;
ThreadStruct consumerInfo, producerInfo;
setValue("The amount of producers", &amountOfProducers, MINIMUM, MAXIMUM);
setValue("The amount of consumers", &amountOfConsumers, MINIMUM, MAXIMUM);
setValue("The size of the buffer", &size, 1, 80);
resetFibo(&numbers);
setValue("The sleeping time for producers", &producerInfo.sleep, 0, 10000);
setValue("The sleeping time for consumers", &consumerInfo.sleep, 0, 10000);
setValue("The limit for the fibonumber", &producerInfo.limit, 0, 35000000000000000);
consumerInfo.limit = producerInfo.limit;
HANDLE hProducer[MAXIMUM];
DWORD dwProducer[MAXIMUM];
HANDLE hConsumer[MAXIMUM];
DWORD dwConsumer[MAXIMUM];
buffer = createBuffer(size);
/* Create the Mutexes */
fiboMutex = CreateMutex(NULL, FALSE, NULL);
bufferMutex = CreateMutex(NULL, FALSE, NULL);
/* Create the Events */
eBufferNotFull = CreateEvent(NULL, FALSE, TRUE, TEXT("buffer_niet_vol"));
eBufferNotEmpty = CreateEvent(NULL, FALSE, FALSE, TEXT("buffer_niet_leeg"));
/* Create the producer threads*/
for (int i = 0; i < amountOfProducers; ++i) {
hProducer[i] = CreateThread(NULL, // No security
0, // Use default stack size
(LPTHREAD_START_ROUTINE)producer,
&producerInfo, // Thread argument
0, // Child became running
(LPDWORD)&dwProducer[i]); // Child id
}
/* Create the consumer threads*/
for (int i = 0; i < amountOfConsumers; ++i) {
hConsumer[i] = CreateThread(NULL, // No security
0, // Use default stack size
(LPTHREAD_START_ROUTINE)consumer,
&consumerInfo, // Thread argument
0, // Child became running
(LPDWORD)&dwConsumer[i]); // Child id
}
WaitForMultipleObjects(amountOfProducers, hProducer, true, INFINITE);
WaitForMultipleObjects(amountOfConsumers, hConsumer, true, INFINITE);
deleteBuffer(buffer);
return (EXIT_SUCCESS);
}
DWORD WINAPI producer(LPVOID lpParameter) {
ThreadStruct *info = (ThreadStruct *)lpParameter;
while (true) {
Sleep(info->sleep);
WaitForSingleObject(fiboMutex, INFINITE); // Lock the fibonumber struct
createNewFibonumber();
if (numbers.currentFibo > info->limit) {
ReleaseMutex(fiboMutex); // Release the fibonumber struct
ExitThread(EXIT_SUCCESS);
}
WaitForSingleObject(eBufferNotFull, INFINITE);
WaitForSingleObject(bufferMutex, INFINITE);
putElement(buffer, numbers.currentFibo);
ReleaseMutex(fiboMutex); // Release the fibonumber struct
ReleaseMutex(bufferMutex);
SetEvent(eBufferNotEmpty);
}
}
DWORD WINAPI consumer(LPVOID lpParameter) {
ThreadStruct *info = (ThreadStruct *)lpParameter;
while (true) {
Sleep(info->sleep);
WaitForSingleObject(eBufferNotEmpty, INFINITE);
WaitForSingleObject(bufferMutex, INFINITE);
printf(" fibogetal: %i \n", getElement(buffer));
ReleaseMutex(bufferMutex);
SetEvent(eBufferNotFull);
}
ExitThread(EXIT_SUCCESS);
}
void createNewFibonumber() {
uint64_t i = numbers.currentFibo;
numbers.currentFibo += numbers.lastFibo;
numbers.lastFibo = i;
}
void resetFibo(Fibonumbers *numbers) {
numbers->lastFibo = 0;
numbers->currentFibo = 1;
}
void setValue(char *text, void *intpointer, uint64_t minimum, uint64_t maximum) {
printf("%s\n", text);
do {
*(uint64_t *)intpointer = 0;
printf("Enter a value from %lli up to %lli : ", minimum, maximum);
scanf_s("%lli", intpointer);
} while (*(uint64_t *)intpointer < minimum || *(uint64_t *)intpointer > maximum);
}
Fibonacci.h
#include <stdio.h>
#include <stdint.h>
#include <conio.h>
#include <Windows.h>
#include "Buffer.h"
typedef struct {
uint64_t currentFibo;
uint64_t lastFibo;
} Fibonumbers;
typedef struct {
uint64_t limit;
uint16_t sleep;
} ThreadStruct;
/*
*
*/
DWORD WINAPI producer(LPVOID lpParameter);
/*
*
*/
DWORD WINAPI consumer(LPVOID lpParameter);
/*
*
*/
void createNewFibonumber();
/*
*
*/
void resetFibo(Fibonumbers *numbers);
/*
*
*/
void setValue(char *text, void *intpointer, uint64_t minimum, uint64_t maximum);
And the Buffer.c
#include "Buffer.h"
CircularBuffer *createBuffer(uint8_t size) {
CircularBuffer *buffer = (CircularBuffer *)calloc(1, sizeof(CircularBuffer));
buffer->size = size;
buffer->count = 0;
buffer->start = 0;
buffer->end = 0;
buffer->buffer = (uint64_t *)calloc(buffer->size, sizeof(uint64_t));
return buffer;
}
void deleteBuffer(CircularBuffer *buffer) {
if (buffer) {
free(buffer->buffer);
free(buffer);
}
}
void putElement(CircularBuffer *buffer, uint64_t element) {
buffer->count++;
buffer->buffer[buffer->start] = element;
buffer->start++;
if (buffer->start == buffer->size) {
buffer->start = 0;
}
printf("put: %i items in buffer.\n", buffer->count);
}
uint64_t getElement(CircularBuffer *buffer) {
buffer->count--;
uint64_t value = buffer->buffer[buffer->end];
buffer->end++;
if (buffer->end == buffer->size) {
buffer->end = 0;
}
printf(" get: %i items in buffer.\n", buffer->count);
return value;
}
bool isBufferFull(CircularBuffer *buffer) {
return (buffer->count == buffer->size);
}
bool isBufferEmpty(CircularBuffer *buffer) {
return (buffer->count == 0);
}
Buffer.h
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
uint64_t *buffer;
uint8_t size;
uint8_t count;
uint8_t start;
uint8_t end;
} CircularBuffer;
CircularBuffer *createBuffer(uint8_t size);
void deleteBuffer(CircularBuffer *buffer);
void putElement(CircularBuffer *buffer, uint64_t element);
uint64_t getElement(CircularBuffer *buffer);
bool isBufferFull(CircularBuffer *buffer);
bool isBufferEmpty(CircularBuffer *buffer);
If someone wishes to also check out the header files, please say so.
edit: I have updated the code, it is now fully functional.
edit2: The program works when I build it under debug mode, but when build under release mode it seems to not start the threads.
Wrong sized allocation
I find this line to be highly suspicious:
buffer->buffer = (uint64_t *)calloc(buffer->size, sizeof(unsigned int));
If buffer->buffer is an array of uint64_t, why are you using sizeof(unsigned int) to allocate it? I don't know if that is your problem, but it's at least one thing that should be fixed up.

Resources