Vulkan API and C - Query for physical device properties causes segfault - c

This is the main caller function
void createVulkanContext()
{
queueFamilyCount = 0;
populatePhysicalDevice(&instance, &physicalDevice);
physicalDeviceTest(&physicalDevice); // This one works fine
populateQueueFamilies(physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, surface);
physicalDeviceTest(&physicalDevice); // This one causes segfault
}
and this is the query function
void physicalDeviceTest(VkPhysicalDevice* gPhysicalDevice)
{
printf("%p\n", gPhysicalDevice);
VkPhysicalDeviceProperties pdProp;
vkGetPhysicalDeviceProperties(*gPhysicalDevice, &pdProp);
printf("%u\n", pdProp.deviceID);
printf("%s\n", pdProp.deviceName);
printf("%u\n", pdProp.apiVersion);
printf("%u\n", pdProp.driverVersion);
printf("%u\n", pdProp.vendorID);
}
which prints this
0x55555555a1e8
26958
Unknown AMD GPU
4198513
8388708
4098
0x55555555a1e8
This is gdb backtrace result
Thread 1 "VulkanApp1090" received signal SIGSEGV, Segmentation fault.
0x00007ffff7f63467 in vkGetPhysicalDeviceProperties () from /usr/lib/libvulkan.so.1
(gdb) backtrace
#0 0x00007ffff7f63467 in vkGetPhysicalDeviceProperties () from /usr/lib/libvulkan.so.1
#1 0x0000555555555602 in physicalDeviceTest (gPhysicalDevice=0x55555555a1e8 <physicalDevice>)
As far as I know this should not happen because populateQueueFamilies(physicalDevice, &queueFamilyIndicesList ...) function doesn't really change physicalDevice variable which is being passed by value.
Full code
typedef struct QueueFamilyIndices
{
int graphicsFamilySupportQueueIndex;
int computeFamilySupportQueueIndex;
int transferFamilySupportQueueIndex;
int sparsebindingFamilySupportQueueIndex;
int protectedFamilySupportQueueIndex;
int presentFamilySupportQueueIndex;
} QueueFamilyIndices;
VkInstance instance;
VkPhysicalDevice physicalDevice;
VkDevice logicalDevice;
QueueFamilyIndices* queueFamilyIndicesList;
QueueFamilyIndices selectedQueueFamilyIndex;
uint32_t queueFamilyCount;
VkQueue graphicsQueue;
VkSurfaceKHR surface;
void populateQueueFamilyQueueIndices(VkQueueFamilyProperties gQueueFamilyProperties,
uint32_t gQueueFamilyIndex,
QueueFamilyIndices* gQueueFamilyIndices)
{
gQueueFamilyIndices->graphicsFamilySupportQueueIndex = -1;
gQueueFamilyIndices->computeFamilySupportQueueIndex = -1;
gQueueFamilyIndices->transferFamilySupportQueueIndex = -1;
gQueueFamilyIndices->sparsebindingFamilySupportQueueIndex = -1;
gQueueFamilyIndices->protectedFamilySupportQueueIndex = -1;
if (gQueueFamilyProperties.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
gQueueFamilyIndices->graphicsFamilySupportQueueIndex = gQueueFamilyIndex;
}
if (gQueueFamilyProperties.queueFlags & VK_QUEUE_COMPUTE_BIT)
{
gQueueFamilyIndices->computeFamilySupportQueueIndex = gQueueFamilyIndex;
}
if (gQueueFamilyProperties.queueFlags & VK_QUEUE_TRANSFER_BIT)
{
gQueueFamilyIndices->transferFamilySupportQueueIndex = gQueueFamilyIndex;
}
if (gQueueFamilyProperties.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT)
{
gQueueFamilyIndices->sparsebindingFamilySupportQueueIndex = gQueueFamilyIndex;
}
if (gQueueFamilyProperties.queueFlags & VK_QUEUE_PROTECTED_BIT)
{
gQueueFamilyIndices->protectedFamilySupportQueueIndex = gQueueFamilyIndex;
}
}
void populateQueueFamilies(VkPhysicalDevice gPhysicalDevice,
QueueFamilyIndices** gQueueFamilyIndicesList,
uint32_t* gQueueFamilyCount,
VkSurfaceKHR surface)
{
uint32_t queueFamilyCount;
vkGetPhysicalDeviceQueueFamilyProperties(gPhysicalDevice, &queueFamilyCount, VK_NULL_HANDLE);
VkQueueFamilyProperties queueFamilies[queueFamilyCount];
vkGetPhysicalDeviceQueueFamilyProperties(gPhysicalDevice, &queueFamilyCount, queueFamilies);
VkBool32 presentFamilySupported;
*gQueueFamilyIndicesList = malloc(sizeof(QueueFamilyIndices*) * queueFamilyCount);
for (uint32_t i = 0; i < queueFamilyCount; ++i)
{
QueueFamilyIndices gQueueFamilyIndices;
populateQueueFamilyQueueIndices(queueFamilies[i], i, &gQueueFamilyIndices);
presentFamilySupported = false;
vkGetPhysicalDeviceSurfaceSupportKHR(gPhysicalDevice, i, surface, &presentFamilySupported);
gQueueFamilyIndices.presentFamilySupportQueueIndex = presentFamilySupported ? i : -1;
gQueueFamilyIndicesList[i] = malloc(sizeof(QueueFamilyIndices));
*gQueueFamilyIndicesList[i] = gQueueFamilyIndices;
}
*gQueueFamilyCount = queueFamilyCount;
}
void physicalDeviceTest(VkPhysicalDevice* gPhysicalDevice)
{
printf("%p\n", gPhysicalDevice);
VkPhysicalDeviceProperties pdProp;
vkGetPhysicalDeviceProperties(*gPhysicalDevice, &pdProp);
printf("%u\n", pdProp.deviceID);
printf("%s\n", pdProp.deviceName);
printf("%u\n", pdProp.apiVersion);
printf("%u\n", pdProp.driverVersion);
printf("%u\n", pdProp.vendorID);
}
void createVulkanContext()
{
queueFamilyCount = 0;
populatePhysicalDevice(&instance, &physicalDevice);
physicalDeviceTest(&physicalDevice); // This one works fine
populateQueueFamilies(physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, surface);
physicalDeviceTest(&physicalDevice); // This one causes segfault
}
Diagnosing a bit more makes me think
gQueueFamilyIndicesList[i] = malloc(sizeof(QueueFamilyIndices));
*gQueueFamilyIndicesList[i] = gQueueFamilyIndices;
because commenting them out fixes the segfault.
TL;DR
Same function (physicalDeviceTest) called again causes segfault
void createVulkanContext()
{
queueFamilyCount = 0;
populatePhysicalDevice(&instance, &physicalDevice);
physicalDeviceTest(&physicalDevice); // This one works fine
populateQueueFamilies(physicalDevice, &queueFamilyIndicesList, &queueFamilyCount, surface);
physicalDeviceTest(&physicalDevice); // This one causes segfault
}
likely due to these calls
gQueueFamilyIndicesList[i] = malloc(sizeof(QueueFamilyIndices));
*gQueueFamilyIndicesList[i] = gQueueFamilyIndices;
in function populateQueueFamilies although I'm not sure why or how.

Figured it out.
*gQueueFamilyIndicesList = malloc(sizeof(QueueFamilyIndices) * queueFamilyCount);
now properly allocates memory and points to the first block of memory in the list.
De-referencing and equating like this
(*gQueueFamilyIndicesList)[i] = gQueueFamilyIndices;
now works just like I expect it to.
Brackets around gQueueFamilyIndicesList is important because [] operator has precedence over *.
*gQueueFamilyIndicesList[i] = *(*(gQueueFamilyIndicesList + i))
and
(*gQueueFamilyIndicesList)[i] = *((*gQueueFamilyIndicesList) + i)

Related

Struct memory allocation issues for message buffer

I'm trying to use static structs as a buffer for incoming messages, in order to avoid checking the buffer on the MCP2515-external unit. An ISR enters the function with a can_message* value 255 to actually read new messages from my MCP2515.
Other applications register an ID in the message passed as argument, in order to check if the buffer holds any messages with the same value.
This returns wrong IDs, and the rest of the datafields are 0 and uninitialized. What is wrong?
can_message struct:
typedef struct
{
uint8_t id;
uint8_t datalength;
uint8_t data[8];
}can_message;
int CAN_message_receive(can_message* message)
{
static volatile can_message* buffers = (volatile can_message*)0x18FF;
static int birth = 1;
if(birth)
{
for (int i; i < CAN_MESSAGE_UNIQUE_IDS; i++)
{
//These structs gets addresses outside SRAM
buffers[i] = (can_message){0,0,0};
}
birth = 0;
}
if (message == CAN_UPDATE_MESSAGES)
{
/* Sorts messages <3 */
can_message currentMessage;
//These functions are working:
CAN_message_get_from_MCP_buf(&currentMessage, 0);
buffers[currentMessage.id] = currentMessage;
CAN_message_get_from_MCP_buf(&currentMessage, 1);
buffers[currentMessage.id] = currentMessage;
return 0; //returns nothing !
}
if(buffers[message->id].id != 0)
{
printf("test\n");
//This copy gives wrong id and data:
memcpy(message, &buffers[message->id], sizeof(can_message));
buffers[message->id].id = 0;
return 0;
}
return -1;
}
Edit 1:
I did however notice that any buffers[i]-struct gets a totally different address than expected. It does not use the addresses following 0x18FF on the SRAM. Is there any way to change this?
Edit 2:
This is my main-loop:
while (1) {
//printf("tx buf ready: %d\n", MCP2515_TX_buf_empty(0));
//CAN_Loopback_test();
_delay_ms(500);
value = USART_ReadByte(0);
CAN_message_receive(&msg);
printf("CAN_receive: ID: %d, datalength: %d, data: \n",msg.id);
for (int k; k < msg.datalength; k++)
{
printf("%d, ",msg.data[k]);
}
printf("\n");
}
Edit 3: Changing the buffer-pointer to array solved the issue. (It does no longer use the SRAM, but whatever floats my boat)
int CAN_message_receive(can_message* message)
{
static can_message buffers[CAN_MESSAGE_UNIQUE_IDS];
static int birth = 1;
if(birth)
{
for (int i; i < CAN_MESSAGE_UNIQUE_IDS*10; i++)
{
*(char*)(0x18FF+i) = 0;
printf("buffers: %X\n", &buffers[i]);
}
birth = 0;
}
Solved!
Pointer to buffers changed to buffer-array:
int CAN_message_receive(can_message* message)
{
static can_message buffers[CAN_MESSAGE_UNIQUE_IDS];
static int birth = 1;
if(birth)
{
for (int i; i < CAN_MESSAGE_UNIQUE_IDS*10; i++)
{
*(char*)(0x18FF+i) = 0;
printf("buffers: %X\n", &buffers[i]);
}
birth = 0;
}
I would strongly suggest to decouple the ISR logic with the programs own message cache logic. Also the initializing logic with the birth variable looks unnecessary.
I would setup some ring buffer that the ISR can write messages to and from that the main code reads the data into the ID-lookup-buffer.
This would ensure that message updates does not interfere with readouts (at least if you check the read/write indices to your ring buffer) and also eliminates the need to put Mutexes around your whole message buffer.
Currently it smells very badly because of missing read/write synchronization.
// global
#define CAN_MESSAGE_UNIQUE_IDS 50
static can_message g_can_messagebuffers[CAN_MESSAGE_UNIQUE_IDS];
#define MAX_RECEIVEBUFFER 8
static volatile can_message g_can_ringbuffer[MAX_RECEIVEBUFFER];
static volatile int g_can_ringbufferRead = 0;
static volatile int g_can_ringbufferWrite = 0;
// called from ISR
void GetNewMessages()
{
// todo: check ring buffer overflow
can_message currentMessage;
CAN_message_get_from_MCP_buf(&g_can_ringbuffer[g_can_ringbufferWrite], 0);
g_can_ringbufferWrite = (g_can_ringbufferWrite + 1) % MAX_RECEIVEBUFFER;
CAN_message_get_from_MCP_buf(&g_can_ringbuffer[g_can_ringbufferWrite], 1);
g_can_ringbufferWrite = (g_can_ringbufferWrite + 1) % MAX_RECEIVEBUFFER;
}
// called from main loop
void handleNewMessages()
{
while(g_can_ringbufferRead != g_can_ringbufferWrite){
const can_message* currentMessage = &g_can_ringbuffer[g_can_ringbufferRead];
if(currentMessage->id < CAN_MESSAGE_UNIQUE_IDS)
{
g_can_messagebuffers[currentMessage->id] = *currentMessage;
}
g_can_ringbufferRead = (g_can_ringbufferRead + 1) % MAX_RECEIVEBUFFER;
}
}
// called from whoever wants to know
// todo:
// really required a by value interface?
// would it not be sufficient to return a pointer and
// provide an additional interface to mark the message as used?
int getMsg(can_message* message)
{
if(buffers[message->id].id != 0)
{
printf("test\n");
*message = &g_can_messagebuffers[message->id];
g_can_messagebuffers[message->id].id = 0;
return 0;
}
return -1;
}
// alternative to above
const can_message* getMsg(int id)
{
if( (id < CAN_MESSAGE_UNIQUE_IDS)
&& (g_can_messagebuffers[id] != 0))
{
return &g_can_messagebuffers[id].id;
}
return NULL;
}
void invalidateMsg(int id)
{
if(id < CAN_MESSAGE_UNIQUE_IDS)
{
g_can_messagebuffers[id] = 0;
}
}
edit:
after your changes to an message array instead some strange pointer, there is also no need for the setup routine for this code.
edit:
if your micro controller already has a buffer for received messages, then may be it is unnecessary at all to register a ISR and you could empty it from the mainloop directly into your own id-lookup buffer (assuming the mainloop is fast enough)

memory leak in hiredis using valgrind

I ran valgrind on my code which uses hiredis, it points out the following individual lines in my code :
redisAsyncConnect()
redisAsyncConnectUnix()
redisLibuvAttach()
uv_loop_new()
I have used 'redisAsyncDisconnect' to free up the memory for the first two cases, couldn't find the right method for third one. For the fourth one i used uv_stop(). But still valgrind says there is definitely a loss in memory in all the four, what is the right way to release the memory ?
Just doing a simple google search shows the method redisLibuvAttach() just does a simple malloc
static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {
redisContext *c = &(ac->c);
if (ac->ev.data != NULL) {
return REDIS_ERR;
}
ac->ev.addRead = redisLibuvAddRead;
ac->ev.delRead = redisLibuvDelRead;
ac->ev.addWrite = redisLibuvAddWrite;
ac->ev.delWrite = redisLibuvDelWrite;
ac->ev.cleanup = redisLibuvCleanup;
redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p));
if (!p) {
return REDIS_ERR;
}
m emset(p, 0, sizeof(*p));
if (uv_poll_init(loop, &p->handle, c->fd) != 0) {
return REDIS_ERR;
}
ac->ev.data = p;
p->handle.data = p;
p->context = ac;
return REDIS_OK;
}
The method on_close in that file shows you can simply free(handle->data) :
static void on_close(uv_handle_t* handle) {
redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
free(p);
}
Or just make sure that method is called.

kprobe, function scheduling - processor lockup - Linux kernel

I've a function I wrote in order to run a given function on all processors. It works perfectly well in all cases except the following case:
When I try to use it within a kprobe that I registered.
Here's some code:
static DEFINE_MUTEX(entryMutex);
static struct kretprobe my_kprobe = {
.entry_handler = (kprobe_opcode_t *) NULL,
.handler = (kprobe_opcode_t *) process_entry_callback,
.maxactive = 1000,
.data_size = 0
};
static int driver_init(void)
{
my_kprobe.kp.addr = (kprobe_opcode_t*)kallsyms_lookup_name("sys_execve");
if ((ret = register_kretprobe(&my_kprobe)) < 0)
return -1;
return 0;
}
void foo(void* nothing)
{
printk("In foo\n");
}
static int process_entry_callback(struct kretprobe_instance* instance, struct pt_regs* regs)
{
mutex_lock(&entryMutex);
for(int i = 0; i < 4; ++i) // assumes there are 4 processors
run_func(foo, NULL, i);
mutex_unlock(&entryMutex);
return 0;
}
void run_func_wrap(struct function_data* data)
{
data->func(data->context);
wake_up_process(data->waiting_task);
*(data->condition) = TRUE;
}
void run_func(SCHEDULED_FUNC func, void *context, int processor)
{
struct function_data data;
struct task_struct* th;
BOOLEAN condition = FALSE;
wait_queue_head_t queue;
init_waitqueue_head(&queue);
data.func = func;
data.waiting_task = current;
data.context = context;
data.condition = &condition;
th = kthread_create(sched_func_wrap, &data, "th");
kthread_bind(th, processor);
wake_up_process(th);
wait_event(queue, condition);
}
F
After the call to 'run_func' in process_entry_callback I can no longer run any programs. Every time I start a new program it just stuck. After a while I get 'processor lockup' warning in the system log.
I suspect that it has something to do with the IRQ levels.
Any suggestions ?
EDIT:
It also happens when using the following function:
smp_call_function_single
which can be found in smp.c # the Linux kernel source code.
instead of my function:
run_func

Postgresql C function that takes a FLOAT8[] and returns an INT[]?

Could someone please provide a template for a C function that would receive FLOAT8[] values and return INT[] values?
The examples that I have found use the same input numeric type as the output numeric type.
I have not seen any examples that show how to create a new INT[] and return it.
One way:
INT *my_function1(FLOAT8 *float8)
{
INT *zzz = malloc(sizeof(INT) * 10);
zzz[0] = 123;
zzz[1] = 234;
...
return(zzz);
}
Call the above like this:
{
INT *aaa = NULL;
FLOAT8 bbb[10];
...
aaa = my_function1(bbb);
printf("%d, %d\n", aaa[0], aaa[1]); /* Output: "123, 234"
...
if(aaa)
free(aaa);
}
Another way:
void my_function2(FLOAT8 *IN_float8, INT **OUT_int)
{
INT *yyy=malloc(sizeof(INT) * 10);
zzz[0] = 123;
zzz[1] = 234;
...
if(OUT_int)
*OUT_int = yyy;
else
{
free(yyy);
fprintf(stderr, "Oops! You gave me a NULL pointer for OUT_int.\n");
}
return;
}
Call the above like this:
{
INT *aaa = NULL;
FLOAT8 bbb[10];
...
my_function1(bbb, &aaa);
printf("%d, %d\n", aaa[0], aaa[1]); /* Output: "123, 234"
...
if(aaa)
free(aaa);
}

UTHash in function call does iteration once but not second time

I am having some issues with usage of a uthash on a local variable.
My code looks something like this, query_dict is a local variable uthash:
main functions:
query* query_dict = NULL;
split_query_into_terms(querystr, &query_dict);
print_query_struct(&query_dict);
prefetch_tokens(&query_dict);
more closely:
void prefetch_tokens(query** query_dict) {
query* entry;
for(entry=*query_dict; entry != NULL; entry=entry->hh.next) {
handle_token(entry->term);
}
}
void add_term_to_query(query** query_dict, char* term, dictionary_entry* dict_entry) {
// if query in hashtable, increase score:
query* myq = NULL;
if(*query_dict != NULL)
HASH_FIND_STR(*query_dict, term, myq);
if(myq == NULL) {
myq = init_alloc_query(term);
myq->dict_entry = dict_entry;
HASH_ADD_KEYPTR(hh, *query_dict, myq->term, strlen(myq->term), myq);
} else {
myq->score += 1.0f;
}
}
void split_query_into_terms(char* querystr, query** query_dict) {
char* myquery = strdup(querystr);
char* reentrant_saver;
char* token;
token = strtok_r(myquery, " \n", &reentrant_saver);
while(token != NULL) {
dictionary_entry* dict_entry = find_dict_entry(token);
if(dict_entry) {
add_term_to_query(query_dict, token, dict_entry);
}
token = strtok_r(NULL, " \n", &reentrant_saver);
}
}
void print_query_struct(query** query_dict) {
query* entry;
for(entry=*query_dict; entry != NULL; entry=entry->hh.next) {
fprintf(stdout, "%s: %f\n", entry->term, entry->score);
}
}
The call to print_query_struct runs fine, but the call to prefetch tokens, does one iteration, then crashes with:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000001000000000
0x0000000100004959 in prefetch_tokens (query_dict=0x7fff5fbffa30) at search/c_port/search.c:241
241 handle_token(entry->term);
(gdb) bt
0 0x0000000100004959 in prefetch_tokens (query_dict=0x7fff5fbffa30) at search/search.c:241
1 0x00000001000049d2 in search (querystr=0x7fff5fbffbe5 "wash") at search/search.c:255
2 0x0000000100004a20 in main (argc=2, argv=0x7fff5fbffa80) at search/search.c:263
the address, 0x0000001000000000 always being the same.
I have been trying all kinds of different things, but could not get it working.
Does anyone here know what's going on?
structs:
typedef struct {
char* word;
uint32_t byte_offset;
uint32_t occurences;
uint32_t occurences_abstract;
postings_entry* posting;
UT_hash_handle hh; /* makes this structure hashable */
} dictionary_entry;
/* query has a number of terms (strings) */
typedef struct {
char* term;
float score;
dictionary_entry* dict_entry;
UT_hash_handle hh;
} query;
Edit:
I have simplified the code quite a bit and made a smaller runnable example, but in essence, this is the code that fails: http://pastebin.com/qdDiQMG0
compile, then run with ./binary
eg. ./binary "wash help"
Edit 2:
Solved it even though I do not quite understand why it worked:
rewrote the init_alloc_query from:
query* init_alloc_query() {
query* query = malloc(sizeof(query));
query->term = NULL;
return query;
}
to work like this:
void init_alloc_query(query** q) {
*q = malloc(sizeof(query));
(*q)->term = NULL;
}
And everything runs fine.
Solved it even though I do not quite understand why it worked: rewrote the init_alloc_query from:
query* init_alloc_query() {
query* query = malloc(sizeof(query));
query->term = NULL;
return query;
}
to work like this:
void init_alloc_query(query** q) {
*q = malloc(sizeof(query));
(*q)->term = NULL;
}
And everything runs fine.

Resources