I am running SnS on android(L) BT app and using GKI calls under bluedroid. All GKI calls are called from various threads of BT app and we are protecting it by mutex(bionic). It works fine if BT turns on\off for 700+ iteration but after that suddenly i see that the moment mutex gets unlocked by one thread, its value becomes 2 and it does not get back to its old value. I am intitializing the mutex in default manner and really not sure what is happening. In fact i had put buffer padding around mutex to avoid from any corruption but buffer with pattern is not overwritten at all but only the mutex value changes to 2. all threads waiting for this mutex starves.
Please suggest why it can change its value to 2 and how I can stop it.
Line 3121: 01-01 03:30:30.200 1117 15470 E GKI_LINUX: LOCK TRYING : gki addr 0xa4e18e40 **value 16384** value before=1515870810 and after=1515870810
Line 3123: 01-01 03:30:30.200 1117 15470 E GKI_LINUX: LOCKED : gki addr 0xa4e18e40 value 1013858305 value before=1515870810 and after=1515870810
Line 3139: 01-01 03:30:30.200 1117 15470 E GKI_LINUX: UNLOCKED : gki addr 0xa4e18e40 **value 2** value before=1515870810 and after=1515870810 **//ideally it should have been 16384**
P.S. : newbie to linux
Code :
//This function initializes the mutex.
void GKI_init(void)
{
pthread_mutexattr_t attr;
tGKI_OS *p_os;
memset (&gki_cb, 0, sizeof (gki_cb));
gki_buffer_init();
gki_timers_init();
alarm_service_init();
gki_cb.com.OSTicks = (UINT32) times(0);
pthread_mutexattr_init(&attr);
#ifndef __CYGWIN__
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
#endif
p_os = &gki_cb.os;
pthread_mutex_init(&p_os->GKI_mutex, &attr);
/* pthread_mutex_init(&GKI_sched_mutex, NULL); */
/*Store mutex value in backup */
p_os->origval = p_os->GKI_mutex.value;
ALOGE(" backup mutex value is = %d ",p_os->origval);
#if (GKI_DEBUG == TRUE)
pthread_mutex_init(&p_os->GKI_trace_mutex, NULL);
#endif
struct sigevent sigevent;
memset(&sigevent, 0, sizeof(sigevent));
sigevent.sigev_notify = SIGEV_THREAD;
sigevent.sigev_notify_function = (void (*)(union sigval))bt_alarm_cb;
sigevent.sigev_value.sival_ptr = NULL;
if (timer_create(CLOCK_REALTIME, &sigevent, &posix_timer) == -1) {
ALOGE("%s unable to create POSIX timer: %s", __func__, strerror(errno));
timer_created = false;
} else {
timer_created = true;
}
}
void GKI_disable (void)
{
pthread_mutex_lock(&gki_cb.os.GKI_mutex);
}
void GKI_enable (void)
{
pthread_mutex_unlock(&gki_cb.os.GKI_mutex);
//Just after this mutex value is getting changed i.e. GKI_mutex.value =2
}
Everytime GKI_disable/ GKI_enable is called before accessing common resources.
Related
Have a structure declared and defined in shared file.
Both threads create by the Windows API CreateThread() have visibility to the instance of it:
struct info
{
std::atomic<bool> inUse;
string name;
};
info userStruct; //this guy shared between two threads
Thread 1 continually locking/unlocking to write to member in structure (same value for test):
while (1)
{
userStruct.inUse = true;
userStruct.name= "TEST";
userStruct.inUse = false;
}
Thread 2 just reading and printing, only if it happens to catch it unlocked
while (1)
{
while (! userStruct.inUse.load() )
{
printf("** %d, %s\n\n", userStruct.inUse.load(), userStruct.name.c_str());
Sleep(500); //slower reading
}
printf("In Use!\n");
}
Expect to see a lot of:
"In Use!"
and every once if it gets in, when unlocked:
"0, TEST"
..and it does.
But also seeing:
"1, TEST"
If the atomic bool is 1 I do NOT expect to ever see that.
What am I doing wrong?
Your code is not thread safe. The atomic is atomic. But the if statement isn't !
What happens:
Thread 1 Thread 2 Comment
while (! userStruct.inUse.load() ) ---> InUse is false
==> continues loop
inUse = true
==> continues loop already started
printf(...)
In the worst case you could have UB due to a data race (one thread 2 modifies the string, and thread 1 reads the string during the modification).
Solution:
Since you intend to use your atomic as a lock, just use a real lock designed for this kind of synchronisation, using a std::mutex with a std::lock_guard.
For example:
struct info
{
std::mutex access;
string name;
};
The first thread would then be:
while (1)
{
std::lock_guard<std::mutex> lock(userStruct.access); // protected until next iteration
userStruct.name= "TEST";
}
The second thread could then attempt to gain access to mutex in a non-blocking fashion:
while (1)
{
{ // trying to lock the mutex
std::unique_lock<std::mutex> lock(userStruct.access, std::try_to_lock);
if(!lock.owns_lock()){ // if not successful do something else
std::cout << "No lock" <<std::endl;
}
else // if lock was successfull
{
std::cout << "Got access:" << userStruct.name <<std::endl;
}
} // at this stage, the lock is released.
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
Online demo
you are performing 2 distict load on the atomic variable to check then output. the value can change between the loads. also you have a data race on your string variable.
you can fixe it easily by using std::atomic_flag or a mutex
struct info
{
std::atomic_flag inUse;
std::string name;
};
//writer
while (1)
{
if (!userStruct.inUse.test_and_set()) {
userStruct.name= "TEST";
userStruct.inUse.clear();
}
}
//reader
while (1)
{
if (!userStruct.inUse.test_and_set())
{
printf("** %s\n\n", userStruct.name.c_str());
userStruct.inUse.clear();
}
printf("In Use!\n");
}
you can't check the value in atomic_flag because it is almost always a bad idea to check the value of a lock because the value can change before you take your action.
As Tyker pointed out in the comment, you have a race condition.( No need for inner while if its in infinite loop anyway.)
if (! userStruct.inUse.load() )
{
//inUse might change in the middle printf
printf("** %d, %s\n\n", userStruct.inUse.load(), userStruct.name.c_str());
Sleep(500); //slower reading
}
else
printf("In Use!\n");
Solution is to "lock" the reading, but simply doing the following is still not safe:
if (! userStruct.inUse.load() ) //#1
{
//inUse might already be true here, so we didn't lock quickly enough.
userStruct.inUse=true; //#2
printf("** %d, %s\n\n", userStruct.inUse.load(), userStruct.name.c_str());
userStruct.inUse=false;
Sleep(500); //slower reading
}
So, truly safe code is to fuse #1, #2 together:
bool f=false;
//Returns true if inUse==f and sets it to true
if(userStruct.inUse.compare_exchange_strong(f,true))
{
printf("** %d, %s\n\n", userStruct.inUse.load(), userStruct.name.c_str());
userStruct.inUse=false;
Sleep(500); //slower reading
}
solved!: im copying the instance of Map in the new Thread an dont use the reference.
im learning how to use multiple threads. For this im programing a little game where i want the game to run in the main thread and the next chunk of the level shall be loaded in another thread. for this i set up a mutex around a vector to tell the loading thread what to load next. inside this mutex i also have a boolean to tell the thread when tu terminate.
initialising thread in Map::Map()
pending_orders_mutex = SDL_CreateMutex();
can_process_order = SDL_CreateCond();
chunk_loader_thread = SDL_CreateThread(Map::chunk_loader,"chunk_loader_thread",(void*)this);
loading thread
int Map::chunk_loader(void * data)
{
Map map = *(Map*)data;
bool kill_this_thread = false;
Chunk_Order actual_order;
actual_order.load_graphics = false;
actual_order.x = 0;
actual_order.y = 0;
while (!kill_this_thread)
{
SDL_LockMutex(map.pending_orders_mutex); // lock mutex
printf("3-kill_chunk_loader_thread: %d\n", map.kill_chunk_loader_thread);
kill_this_thread = map.kill_chunk_loader_thread;
printf("4-kill_chunk_loader_thread: %d\n", map.kill_chunk_loader_thread);
if (!kill_this_thread)
{
if (map.pending_orders.size())
{
actual_order = map.pending_orders.back();
map.pending_orders.pop_back();
printf("in thread processing order\n");
}
else
{
printf("in thread waiting for order\n");
SDL_CondWait(map.can_process_order, map.pending_orders_mutex);
}
}
SDL_UnlockMutex(map.pending_orders_mutex); // unlock mutex
//load actual order
}
printf("thread got killed\n");
return 0;
}
killing the thread (main thread)
SDL_LockMutex(pending_orders_mutex); // lock mutex
printf("setting kill command\n");
printf("1-kill_chunk_loader_thread: %d\n", kill_chunk_loader_thread);
kill_chunk_loader_thread = true; // send kill command
printf("2-kill_chunk_loader_thread: %d\n", kill_chunk_loader_thread);
SDL_CondSignal(can_process_order); // signal that order was pushed
SDL_UnlockMutex(pending_orders_mutex); // unlock mutex
SDL_WaitThread(chunk_loader_thread, NULL);
console output
3-kill_chunk_loader_thread: 0
4-kill_chunk_loader_thread: 0
in thread waiting for order
setting kill command
1-kill_chunk_loader_thread: 0
2-kill_chunk_loader_thread: 1
3-kill_chunk_loader_thread: 0
4-kill_chunk_loader_thread: 0
in thread waiting for order
why does the mainthread not change the "kill_chunk_loader_thread" boolean in the loading thread?
First of all, you should try to upload a minimal complete program in the question.
Its look like you set kill_chunk_loader_thread = true
but you didn't set map.kill_chunk_loader_thread = true
the section of map declaration is missig from your question, but I guess you didn't use a reference to the local or global variable, or you just perform struct copy so when you change one struct the other doesn't been affected at all.
EDIT:
Map map = *(Map*)data; copies the map structure (default copy constructor, I guess) so from now on if the source map change the copy won't.
You should keep work with the pointer, like this: Map* pMap = (Map*)data;
and check the pointer like this: kill_this_thread = pMap->kill_chunk_loader_thread; so you read from the source map.
I am trying to execute my program in threads, I use pthread_create(), but it runs the threads immediately. I would like to allow the user to change thread priorities before running. How it is possible to resolve?
for(int i = 0; i < threads; i++)
{
pthread_create(data->threads+i,NULL,SelectionSort,data);
sleep(1);
print(data->array);
}
Set the priority as you create the thread.
Replace
errno = pthread_create(..., NULL, ...);
if (errno) { ... }
with
pthread_attr_t attr;
errno = pthread_attr_init(&attr);
if (errno) { ... }
{
struct sched_param sp;
errno = pthread_attr_getschedparam(&attr, &sp);
if (errno) { ... }
sp.sched_priority = ...;
errno = pthread_attr_setschedparam(&attr, &sp);
if (errno) { ... }
}
/* So our scheduling priority gets used. */
errno = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
if (errno) { ... }
errno = pthread_create(..., &attr, ...);
if (errno) { ... }
errno = pthread_attr_destroy(&attr);
if (errno) { ... }
For pthreads the priority isn't set after thread creation but rather by passing suitable attributes upon thread creation: the thread attributes go where you have specified NULL in your pthread_create() call. If you want to delay thread creation until the user has given you a priority you can create a function object expecting the priority and upon call of that function object you'd kick off the thread. Of course, you'll still need to keep track of the thus created object (possibly using a std::future<...>-like object) to later join that thread.
Note that providing an answer shouldn't be construed as endorsing thread priorities: as far as I can tell, playing with thread priorities are ill-advised.
#include <pthread.h>
#include <time.h>
#include "errors.h"
typedef struct alarm_tag {
struct alarm_tag *link;
int seconds;
time_t time; /* seconds from EPOCH */
char message[64];
} alarm_t;
pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER;
alarm_t *alarm_list = NULL;
void *alarm_thread (void *arg)
{
alarm_t *alarm;
int sleep_time;
time_t now;
int status;
while (1) {
status = pthread_mutex_lock (&alarm_mutex);
if (status != 0)
err_abort (status, "Lock mutex");
alarm = alarm_list;
/*
* If the alarm list is empty, wait for one second. This
* allows the main thread to run, and read another
* command. If the list is not empty, remove the first
* item. Compute the number of seconds to wait -- if the
* result is less than 0 (the time has passed), then set
* the sleep_time to 0.
*/
if (alarm == NULL)
sleep_time = 1;
else {
alarm_list = alarm->link;
now = time (NULL);
if (alarm->time <= now)
sleep_time = 0;
else
sleep_time = alarm->time - now;
#ifdef DEBUG
printf ("[waiting: %d(%d)\"%s\"]\n", alarm->time,
sleep_time, alarm->message);
#endif
}
/*
* Unlock the mutex before waiting, so that the main
* thread can lock it to insert a new alarm request. If
* the sleep_time is 0, then call sched_yield, giving
* the main thread a chance to run if it has been
* readied by user input, without delaying the message
* if there's no input.
*/
status = pthread_mutex_unlock (&alarm_mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
if (sleep_time > 0)
sleep (sleep_time);
else
sched_yield ();
/*
* If a timer expired, print the message and free the
* structure.
*/
if (alarm != NULL) {
printf ("(%d) %s\n", alarm->seconds, alarm->message);
free (alarm);
}
}
}
int main (int argc, char *argv[])
{
int status;
char line[128];
alarm_t *alarm, **last, *next;
pthread_t thread;
status = pthread_create (
&thread, NULL, alarm_thread, NULL);
if (status != 0)
err_abort (status, "Create alarm thread");
while (1) {
printf ("alarm> ");
if (fgets (line, sizeof (line), stdin) == NULL) exit (0);
if (strlen (line) <= 1) continue;
alarm = (alarm_t*)malloc (sizeof (alarm_t));
if (alarm == NULL)
errno_abort ("Allocate alarm");
/*
* Parse input line into seconds (%d) and a message
* (%64[^\n]), consisting of up to 64 characters
* separated from the seconds by whitespace.
*/
if (sscanf (line, "%d %64[^\n]",
&alarm->seconds, alarm->message) < 2) {
fprintf (stderr, "Bad command\n");
free (alarm);
} else {
status = pthread_mutex_lock (&alarm_mutex);
if (status != 0)
err_abort (status, "Lock mutex");
alarm->time = time (NULL) + alarm->seconds;
/*
* Insert the new alarm into the list of alarms,
* sorted by expiration time.
*/
last = &alarm_list;
next = *last;
while (next != NULL) {
if (next->time >= alarm->time) {
alarm->link = next;
*last = alarm;
break;
}
last = &next->link;
next = next->link;
}
/*
* If we reached the end of the list, insert the new
* alarm there. ("next" is NULL, and "last" points
* to the link field of the last item, or to the
* list header).
*/
if (next == NULL) {
*last = alarm;
alarm->link = NULL;
}
#ifdef DEBUG
printf ("[list: ");
for (next = alarm_list; next != NULL; next = next->link)
printf ("%d(%d)[\"%s\"] ", next->time,
next->time - time (NULL), next->message);
printf ("]\n");
#endif
status = pthread_mutex_unlock (&alarm_mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
}
}
}
Hi this is my code, can anyone tell me because the mutex is not declared in the struct. So when the mutex locks and unlocks, what data is actually being changed can someone enlighten me?
where is this set of data that is being protected by the mutex?
The mutex object is alarm_mutex. The data "protected" by it doesn't have to be explicitely mentioned in the code; as in, there doesn't need to be a semantic connection. A mutex is a low-level threading primitive and as such the user needs to build his own logic around that. In your case, that one place in memory is used to block other parts of your code, those accessing actual data, from interfering.
Think about it this way: std::atomic<int> x; expresses the atomicity of operations on it. int x; mutex m; requires every piece of the code accessing x to properly look at m to ensure the correctness of the program. This low-level acess is what we're looking at in your example.
pthread_mutex_t alarm_mutex = PTHREAD_MUTEX_INITIALIZER; creates a shared mutex object, used for locking/unlocking.
pthread_mutex_lock locks the mutex as soon as it is available. It becomes unavailable for all other threads after this line is executed.
pthread_mutex_unlock unlocks the mutex, making it available again for other threads (unlocks the pthread_mutex_lock of another thread)
The mutex doesn't know what it is protecting. It is the programmer's job to know that and only change the data that it is protecting while the mutex is locked.
In this specific case it seems that the alarm list is the data being locked.
I wrote a super simple wrapper for a pthread_mutex_t meant to be used between two processes:
//basic version just to test using it between two processes
struct MyLock
{
public:
MyLock() {
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP);
pthread_mutex_init(&lock, &attr);
}
~MyLock() {
pthread_mutex_destroy(&lock);
pthread_mutexattr_destroy(&attr);
}
lock() {
pthread_mutex_lock(&lock);
}
unlock() {
pthread_mutex_unlock(&lock);
}
private:
pthread_mutexattr_t attr;
pthread_mutex_t lock;
};
I am able to see this lock work fine between regular threads in a process but when I run process A which does the following in a shared memory region:
void* mem; //some shared memory from shm_open
MyLock* myLock = new(mem) MyLock;
//loop sleeping random amounts and calling ->lock and ->unlock
Then process B opens the shared memory object (verified by setting it with combinations of characters that it's the same region of memory) and does this:
MyLock* myLock = reinterpret_cast<MyLock*>(mem);
//same loop for locking and unlocking as process A
but process B segfaults when trying to lock with the backtrace leading to pthread_mutex_lock() in libpthread.so.0
What am I doing wrong?
The backtrace I get from process B looks like this:
in pthread_mutex_lock () from /lib64/libpthread.so.0
in MyLock::lock at MyLock.H:50
in Server::setUpSharedMemory at Server.C:59
in Server::Server at Server.C
in main.C:52
The call was the very first call to lock after reinterpret casting the memory into a MyLock*. If I dump the contents of MyLock in gdb in the crashing process I see:
{
attr = {
__size = "\003\000\000\200",
__align = -2147483645
},
lock = {
__data = {
__lock = 1
__count = 0,
__owner = 6742, //this is the lightweight process id of a thread in process A
__nusers = 1,
__kind = 131,
__spins = 0,
__list = {
__prev = 0x0,
__Next = 0x0
}
},
__size = "\001\000\000\000\000 //etc,
__align = 1
}
}
so it looks alright (looks like this in the other process gdb as well). I am compiling both applications together using no additional optimization flags either.
You didn't post the code to open and initialize a shared memory region but I suspect that part might be responsible for your problem.
Because pthread_mutex_t is much larger than "combination of characters," you should check your shm_open(3)-ftruncate(2)-mmap(2) sequence with reading and writing a longer (~ KB) string.
Dont't forget to check both endpoints can really write to the shm region and the written data is really visible to the other side.
Process A: [open and initialize the shm]-[write AAA...AA]-[sleep 5 sec]-[read BBB...BB]-[close the thm]
Process B: (a second or two later) [open the shm]-[read AAA...AA]-[write BBB...BB]-[close the thm]
I have a similar issue where the writer Process is root and the Readers Processes are regular users (case of a hardware daemon).
This would segfault in Readers as soon as any pthread_mutex_lock() or pthread_cond_wait() and their unlock counterparts were called.
I solved it by modifying the SHM file permissions using an appropriated umask:
Writer
umask(!S_IRUSR|!S_IWUSR|!S_IRGRP|!S_IWGRP|!S_IROTH|!S_IWOTH);
FD=shm_open("the_SHM_file", O_CREAT|O_TRUNC|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
ftruncate(FD, 28672);
SHM=mmap(0, 28672, PROT_READ|PROT_WRITE, MAP_SHARED, FD, 0);
Readers
FD=shm_open("the_SHM_file", O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
SHM=mmap(0, 28672, PROT_READ|PROT_WRITE, MAP_SHARED, A.FD, 0);
You don't say what OS you are using, but you don't check the return value of the pthread_mutexattr_setpshared call. It's possible your OS does not support shared mutexes and this call is failing.