How can I get platform specific information on stack limits - garbage-collection

I'm playing around with making an interpreter that does memory allocation in the style of Chicken Scheme. The basic idea is:
int main() {
instruction instructions[] = { zero_root, print_root, hello_world,
hello_world, stop };
top_ip.go = &instructions[0];
setjmp(top);
(*top_ip.go)(top_ip);
return 0;
}
89,10-17 Bot
and
/* The following function is machine dependent */
static bool is_time_to_gc(){
/* Is allocated on the stack */
char stack_top;
/* It's address is therefore the stack's top */
return &stack_top >= STACK_LIMIT;
}
static void goto_next_instruction(struct instruction_pointer ip) {
++ip.go;
if (is_time_to_gc()) {
/*
* Some complicated garbage collection stuff which I haven't
* completed yet.
*/
top_ip.go = ip.go;
longjmp(top, 0);
}
(*ip.go)(ip);
}
and a sample instruction is:
static void hello_world(struct instruction_pointer ip) {
printf("Hello World!\n");
goto_next_instruction(ip);
}
What I need to know is what the value for STACK_LIMIT should be (I also need to know if the stack grows up or downwards.) How can I get platform specific information on stack limits?

man getrlimit.
also check the limits imposed by your shell usually in /etc/login.conf
(if it's an sh derivative you can view them by typing limit).
:)
cheers.

Related

kernel module: reading existing proc file (proc_create)

I am an absolute newbie on Linux kernel. Sincere apologies if this has been answered. I have spent many hours and could not resolve it and hence decided to ask (reading Linux device drivers book as well). My problem statement: I would like to read a proc file (/proc/pid/maps) in my kernel module (a few more). There are numerous examples on proc_create which create a file and then write/read to it. I just want a read to the existing proc file. It appears all the previous options have been deprecated (read_proc, create_proc_read_entry and so on). An option that I read is to call proc_pid_maps_operations from task_mmu.c. This is involved when /proc/pid/maps is called? Is that the right approach? Or I can abstract it.
Code snippet of proc_create from various tutorials is here. The moment I change the name to an existing file, insmod fails.
if (!proc_create( "testcpuinfo", // define ENTRY_NAME "hello_world"
0, // permissions 0644
NULL, // proc directory
&fops)) // file_operations
{
printk("ERROR! proc_create\n");
remove_proc_entry(ENTRY_NAME, NULL);
return -ENOMEM;
}
I asked this question as I wanted to filter out /proc/pid/maps. It has a large number of entries and impacting the performance of my workload. Thanks to #0andriy and #Tsyvarev for guiding me as a newbie. I have included the code I have to filter and generate modified maps. I have attached code snippet in case it helps a newbie like me in generating their version of /proc/pid/maps.
static int proc_show(struct seq_file *s, void *v) {
struct task_struct *task;
struct pid *pid_struct;
struct mm_struct *mm;
struct vm_area_struct *vma;
unsigned long start, end;
const char *region = NULL;
// Look for task which PID was provided as parameter, falling back to current task if not found
if(pid == 0) {
printk(KERN_INFO "pages_activity: no pid argument provided, using current process instead\n");
task = current;
} else {
pid_struct = find_get_pid(pid);
if(pid_struct == NULL) {
printk(KERN_INFO "pages_activity: process with pid %d not found, using current process instead\n", pid);
task = current;
} else {
task = pid_task(pid_struct, PIDTYPE_PID);
}
}
mm = task->mm;
vma = mm->mmap;

Correct interactions between Linux kernel wait-queues and lists

I'm writing a Linux kernel module which involves a list being read/written from different process contexts and feel I'm missing functionality equivalent to pthread_cond_wait() and co. from user-space.
Naively I might write something like this:
static LIST_HEAD(request_list);
static DEFINE_MUTEX(request_list_mutex);
static DECLARE_WAIT_QUEUE_HEAD(request_list_post_wq);
static void post_request(request_t *request)
{
mutex_lock(request_list_mutex);
list_add(request, request_list);
mutex_unlock(request_list_mutex);
wake_event(request_list_post_wq);
}
static void wait_and_consume_request()
{
mutex_lock(request_list_mutex);
if(list_empty(request_list)) {
mutex_unlock(request_list_mutex);
wait_event(request_list_post_wq, !list_empty(request_list));
mutex_lock(request_list_mutex);
}
// do something with request
mutex_unlock(request_list_mutex);
}
However, this looks like it will have a race condition in the consumer function between waking on a non-empty list and then re-acquiring the mutex if there are multiple consumers. At the same time I have to release the mutex before waiting otherwise nothing will ever be able to add to the list.
I considered writing a function which locks the request_list, and only unlocks it if it's still empty and use this as the conditional to wait_event... but googling around I've seen lots of examples of people writing wait_event(...., !list_empty(...)) so I must be missing something?
The helper function that the other person suggested isn't needed at all:
static int list_is_not_empty()
{
int rv = 1;
mutex_lock(request_list_mutex);
rv = !list_empty(request_list);
mutex_unlock(request_list_mutex);
return rv;
}
There's no need to lock the list just to see if it's empty or not. So simply:
static void wait_and_consume_request()
{
wait_event(request_list_post_wq, !list_empty(request_list));
mutex_lock(request_list_mutex);
if(!list_empty(request_list)) {
// do something with request
}
mutex_unlock(request_list_mutex);
}
But this won't guarantee that you actually consume a request. If we do want to ensure that we consume exactly one request, then:
static void wait_and_consume_request()
{
mutex_lock(request_list_mutex);
while(list_empty(request_list)) {
mutex_unlock(request_list_mutex);
wait_event(request_list_post_wq, !list_empty());
lock_mutex();
}
// do something with request
mutex_unlock(request_list_mutex);
}
Here's a real example from the kernel in drivers/misc/carma/carma-fpga.c (I just took the first example that I could see)
spin_lock_irq(&priv->lock);
/* Block until there is at least one buffer on the used list */
while (list_empty(used)) {
spin_unlock_irq(&priv->lock);
if (filp->f_flags & O_NONBLOCK)
return -EAGAIN;
ret = wait_event_interruptible(priv->wait, !list_empty(used));
if (ret)
return ret;
spin_lock_irq(&priv->lock);
}
/* Grab the first buffer off of the used list */
dbuf = list_first_entry(used, struct data_buf, entry);
list_del_init(&dbuf->entry);
spin_unlock_irq(&priv->lock);

need assistance with race conditions

Below is an example of the code
#define MAX PROCESSES 255
int number_of_processes = 0;
/* the implementation of fork() calls this function */
int allocate process()
{
int new pid;
if (number_of_processes == MAX PROCESSES)
return -1;
else {
/* allocate necessary process resources */
++number_of_processes;
return new pid;
}
}
/* the implementation of exit() calls this function */
void release process()
{
/* release process resources */
--number_of_processes;
}
I know the race condition is number_of_processes. I am trying to understand race conditions. My question is if i had a mutex lock with acquire() and release() operations, where could i place the lock to avoid race conditions. I just started reading about process synchronization and its pretty interesting. Also could an atomic integer be used such as atomic_t number_of_processes instead of int number_of_processes. I know atomic integer is used to avoid context switching but am not sure but is it possible?
Consider changing the code in that way, for mutex lock:
#define MAX PROCESSES 255
int number_of_processes = 0;
/* the implementation of fork() calls this function */
int allocate_process()
{
try {
lock.acquire();
int new pid;
if (number_of_processes == MAX PROCESSES)
return -1;
else {
/* allocate necessary process resources */
++number_of_processes;
return new pid;
}
} finally {
lock.release();
}
}
/* the implementation of exit() calls this function */
void release_process()
{
try {
lock.acquire();
/* release process resources */
--number_of_processes;
} finally {
lock.release();
}
}
I used try/finally syntax from Java, it might be slightly different for C++.
Regadring atomic integer - simple replace of int with atomic_t won't help because there are two operations with number_of_processes in allocate_process, thus the whole operation is not atomic.

Is there a portable way to give thread name with Qt?

I know I can set thread name (the one visible in gdb and htop) in Linux using prctl(). But with another OSes this most likely won't work. Also, I could try using pthread_setname_np(), which is a bit more available across POSIX systems, but still lacks full compatibility.
So I'd like to have some more portable way, maybe something QThread provides which I've not found. Is there any such way?
There's nothing in the QThread API to manually manage the system name of the thread, however, since version 4.8.3, Qt will automatically set the name of your thread to the name of the thread object (QObject::objectName()).
This is handled in the implementations of QThread as described below.
You have something like this in qthread_unix.cpp:
#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
static void setCurrentThreadName(pthread_t threadId, const char *name)
{
# if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
Q_UNUSED(threadId);
prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
# elif defined(Q_OS_MAC)
Q_UNUSED(threadId);
pthread_setname_np(name);
# elif defined(Q_OS_QNX)
pthread_setname_np(threadId, name);
# endif
}
#endif
/*
* [...]
*/
QString objectName = thr->objectName();
if (Q_LIKELY(objectName.isEmpty()))
setCurrentThreadName(thr->d_func()->thread_id, thr->metaObject()->className());
else
setCurrentThreadName(thr->d_func()->thread_id, objectName.toLocal8Bit());
And the equivalent in qthread_win.cpp:
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // must be 0x1000
LPCSTR szName; // pointer to name (in user addr space)
HANDLE dwThreadID; // thread ID (-1=caller thread)
DWORD dwFlags; // reserved for future use, must be zero
} THREADNAME_INFO;
void qt_set_thread_name(HANDLE threadId, LPCSTR threadName)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = threadId;
info.dwFlags = 0;
__try
{
RaiseException(0x406D1388, 0, sizeof(info)/sizeof(DWORD), (const ULONG_PTR*)&info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
}
}
/*
* [...]
*/
QByteArray objectName = thr->objectName().toLocal8Bit();
qt_set_thread_name((HANDLE)-1, objectName.isEmpty() ? thr->metaObject()->className() : objectName.constData());
Note that on Windows, the above code won't be executed if QT_NO_DEBUG is set, thus it won't work in Release mode.
In Qt documentation you can find:
To choose the name that your thread will be given (as identified by
the command ps -L on Linux, for example), you can call setObjectName()
before starting the thread. If you don't call setObjectName(), the
name given to your thread will be the class name of the runtime type
of your thread object (for example, "RenderThread" in the case of the
Mandelbrot Example, as that is the name of the QThread subclass). Note
that this is currently not available with release builds on Windows.

address allocation in linux : possible over lap?

I am trying to check if my program is assigning memory correctly -
so i have series of pointers of different types,
pData1 = 0x844c458 ( result of malloc(5 * size of (double*))
pData2 = 0x844c470 (result of malloc (10 size of (double));
pData3 = 0x844c3a0(result of malloc(44 * size 0f (double*));
pData4 = 0x844c358
So i think double = 8 bytes , 5 *8 = 40 bytes, which means first two addresses will overlap and similarly last two ?
I am getting invalid free, so i am investigating a memory corruption in my code so trying to find where this might be happening.
-----Edit ------- Adding code details
THis is the struct -
struct _ELEMENT
{
short s;
char arr[20];
int size;
void *ptr1;
void *ptr2;
}ELEMENT;
There are two classes Parent and Derived ( child of Parent)
Class Parent
{
protected:
int size;
ELEMENT *ele1;
ELEMENT *ele2;
public:
void func();
...
}
Class Child::public Parent
{
int a,b,c;
}
Parent::Parent()
{
ele1 = NULL;
ele2= NULL;
}
Parent::~Parent()
{
for (int i =0; i< size; i++)
{
free(ele1[i].p1);
free(ele2[i].p1);
}
free(ele1);
free(ele2);
}
Child::Child()
{
a=0;...
}
Child::~Child()
{
for (int i =0; i< size; i++)
{
free(ele1[i].p1);
free(ele2[i].p1);
}
free(ele1);
free(ele2);
}
Parent::func ()
{
ele1 = (ELEMENT*)malloc (n * sizeof(ELEMENT));
ele2 = (ELEMENT*)malloc (n* sizeof(ELEMENT));
for (int i =0; i <somenumber; i++)
{
...some processing...
ele1[i].size = n;
ele2[i].size = x;
ele1[i].p1 = malloc (ele1[i].size);
ele2[i].p1 = malloc(ele2[i].size);
}
}
main ()
{
Parent *p;
CHild *c;
p = new Parent();
c= new Child();
p->func();
c->func();
delete(p);
delete(c);
}
The _glibc:invalid free comes at first free of parent destructor. This code was working fine in SOlaris for years but porting it in linux is giving this issue...
Thanks!
The answer to your question is that your program is allocating memory correctly, the first problem you had/have is that you don't know the size of your data types and so your computations are incorrect.
If you would post your code and the actual errors that you are getting, it's possible that we can figure this out. As it is, the deep problem of invalid free cannot be answered.
To whom it may concern, is this an answer or a comment?
sizeof(double) is 8 bytes and sizeof(double*) is 4 (on your 32 bit system).
Memory obtained by malloc will not overlap unless freed in the meantime.
Use a memory debugger such as valgrind
It looks that way... how did you end up with these pointers? In principle it's OK to have different pointers pointing to the same space - you just shouldn't be "freeing" except from a pointer that was assigned with malloc (or calloc). The glibc actually keeps some data "just below the pointer" that tells it how big the block is etc, so it can free "cleanly". If you change the value of the pointer, you can't "free part of a block" since the information about how big the block is isn't available (only if the pointer is unchanged). Could that be the source of your problem?

Resources