I'd like to know how are mutex created on Linux? I figured out, that pthread_mutex_init() doesn't change value of pthread_mutex_t variable, so how it "create" mutex?
Does it mark this variable as some kind of system resource or what?
I was implementing R-value constructor for class, which have a pthread_mutex_t field in it's body and I don't know how to move mutex frome one class to another...
You can see what pthread_mutex_init does here (warning, you brain will hurt).
It does memset() the mutex.
However, mutexes are implemented on top of the futex calls. This works on memory addresses, i.e.
the address of one of the pthread_mutex_t members is used as a system resource.
This means you cannot copy/move a pthread_mutex_t.
It seems like you want to pass ownership of the mutex to another class. Are you sure that is the correct way to solve your problem? If you absolutely need to do it though, you could create an auto_ptr to pass ownership around:
class A
{
A(const A & other) mutex(other.mutex) { /* ... */ }
auto_ptr<pthread_mutex_t> mutex;
}
Related
The standard library provides a mutex class, with the ability to manually lock and unlock it:
std::mutex m;
m.lock();
// ...
m.unlock();
However, the library apparently also recognizes that a common case is just to lock the mutex at some point, and unlock it when leaving a block. For this it provides std::lock_guard and std::unique_lock:
std::mutex m;
std::lock_guard<std::mutex> lock(m);
// ...
// Automatic unlock
I think a fairly common pattern for threads, is to create one (either as a stack variable, or a member), then join it before destructing it:
std::thread t(foo);
// ...
t.join();
It seems easy to write a thread_guard, which would take a thread (or a sequence of threads), and would just call join on its own destruction:
std::thread t(foo);
thread_guard<std::thread> g(t);
// ...
// Join automatically
Is there a standard-library class like it?
If not, is there some reason to avoid this?
This issue is discussed in Scott Meyer's book "Modern Effective c++"
The problem is that if there would be another default behavior (detach or join) would cause hard to find errors in case you forget that there is a implicit operation. So the actual default behavior on destruction is asserting if not explicitly joined or detached. And no "Guard" class is there also because of that reason.
If you always want to join it's safe to write such a class yourself. But when someone uses it and wants to detach people can forget that the destructor will implicitly join it. So that's the risk in writing such function.
As an alternative you can use a scope_guard by boost or the folly library (which I personally prefer more) and declare in the beginning explicitly your intention and it will be executed. Or you can write a policy based "Guard" class where you have to explicitly state what you want to do on destruction.
I have a function which is called by multiple functions. Some functions call it with spinlock held and some without any lock. How can I know if my function is called with spinlock held?
I have a big piece of code written some time back. It has some functions which are called with and without locks from different code paths. The functions allocate skbs with GFP_KERNEL flag only considering the cases without locks. It is causing issues when called with spin_lock(). I need to handle both the cases to avoid sleeping inside a spin_lock.
How can I know if my function is called with spinlock held?
You cannot, not directly. You would need to set a flag in some structure yourself that indicates whether you hold the lock or not.
You are better off creating 2 functions. One that you call if you hold the lock, one that you call if you don't hold the lock.
//b->lck must be taken
void foo_unlocked(struct bar *b)
{
//do your thing, assume relevant lock is held
}
//b->lck must not be taken
void foo(struct bar *b)
{
spin_lock(b->lck);
foo_unlocked(b);
spin_unlock(b->lck);
}
I need to check only preemption disabled or irqs disabled. Based on that I can allocate memory with GFP_KERNEL or GFP_ATOMIC. Hence I don't need to rely on when spin_lock or another lock. Using in_atomic() and irqs_disabled() functions, I can achieve it. Thanks
I have a template class similar to this one:
template <typename T>
class Foo {
public:
static void show () {
unique_lock<mutex> l {mtx};
for (const auto& v : vec) {
cout << v << endl;
}
}
static void add (T s) {
unique_lock<mutex> l {mtx};
vec.push_back (s);
}
private:
static mutex mtx;
static vector<T> vec;
};
template <typename T> mutex Foo<T>::mtx;
template <typename T> vector<T> Foo<T>::vec;
And usage of this class looks like this:
Foo<string>::add ("d");
Foo<string>::add ("dr");
Foo<string>::add ("dre");
Foo<string>::add ("drew");
Foo<string>::show ();
Could you tell me if this class is thread-safe? And if it is not, how to make a thread safe version?
If I understand it correctly when we have a class with member functions (not static) and mutex (not static), we prevent race condition of the single object which has been passed across threads, right? And when we have something similar to this we prevent race condition not for the object but for the class instead - in this case for particular type, or am I wrong?
Looks good to me. Up and to a point.
mtx is 'guarding' vec to ensure that the iteration in show() can not be taking place while the vector is being modified during add().
Consider calling it vec_mtx if that is its role.
Up and to a point?
Firstly, your use doesn't (in fact) indicate any threading taking place so I don't (quite) know what you're trying to achieve.
For example if all those adds were taking place in one thread and show in another, your code (obviously) won't ensure that they have all taken place before show.
It will only ensure that (logically) it takes place either before all of them, strictly between two of them or after all of them.
Although not applicable to your use case if you retained references to string objects you passed in or used a type T with a 'shallow' copy constructor then you might be in trouble.
Consider Foo::add(buffer); and continue modifying buffer such that show() is executing in one thread while strcat(buffer,.) is executing on another and buffer is temporarily not '\0' terminated. Boom! Book a ticket to Seg Fault City (where the grass aint green and the girls aint pretty).
You need to look hard (real hard) at what data is being shared and how.
Almost all unqualified statements 'X is thread-safe' are false for all X.
You should always (always) qualify what uses they are safe for and/or how far their safety extends.
That goes 10 times for templates.
Almost all template 'guarantees' can be blown by using some kind of C array (or complex structure holding a pointer or referenced elsewhere, passing it into template in a thread here while smacking it about over there. Your efforts to make an internal copy will themselves be unsafe!
There's a recurring fallacy that if you share data through some kind of thread-safe exchange structure such as a queue you get some kind of thread-safe guarantee and you never need to think about it again and can go back to your single threaded thinking.
Here endeth the lesson.
NB: In theory std::string could be implemented on a memory starved environment that aggressively 'pools' copy strings in a way that exposes you to race conditions you haven't even imagined. Theory you understand.
I have some questions about pthreads in linux:
Is it the case that pthread_t is it a datatype similar to int and char indicating we are defining a thread?
If so, how much size does it take? 2 bytes or 4 bytes?
Does the compiler allocate memory to pthread_t thread1 immediately after that statement or does it wait until it a pthread_create() call?
How does one set the thread attributes, and what is their typical use?
Can one only pass more than one argument in the pthread_create() call? If so, how?
I have lots of things on my mind like this. Please also feel free to suggest any good sites or documents to read.
Answering the questions one by one, though not necessarily in the same order:
Is pthread_t a data type similar to int or char, indicating we are defining a thread ? Does the compiler allocate memory to pthread_t thread1 immediately after that sentence or does it wait until it finds the pthread_create() call
pthread_t is a type similar to int and it's created when you define it, not when you call pthread_create. In the snippet:
pthread_t tid;
int x = pthread_create (&tid, blah, blah, blah);
it's the first line that creates the variable, although it doesn't hold anything useful until the return from pthread_create.
How much size does a pthread_t take, 2 bytes or 4 bytes?
You shouldn't care how much space it takes, any more than you should care how much space is taken by a FILE structure. You should just use the structure as intended. If you really want to know, then sizeof is your friend.
Any good information about how to set the thread attributes?
If you want to use anything other than default attributes, you have to create an attributes variable first and then pass that to the pthread_create call.
Can we only pass one argument in the pthread_create function to the function? Can't we send 2 or 3 arguments in the pthread_create() function to the called thread?
While you're only allowed to pass one extra parameter to the thread , there's nothing stopping you from making this one parameter a pointer to a structure holding a hundred different things.
If you're looking for information on how to use pthreads, there's plenty of stuff at the end of a Google search but I still prefer the dead-tree version myself:
how much size does it take
pthread_t uses sizeof pthread_t bytes.
and we can only pass one argument in the pthread_create to the function not more than one? cant we send 2 or 3 arguments in the pthread_create() function to the called thread?
All you need is one argument. All you get is one argument. It's a void * so you can pass a pointer to whatever you want. Such as a structure containing multiple values.
i have lots of things on my mind like this suggest any good sites or documents to read
Have a look at the pthread man pages, online or in your shell of choice (man pthread, man pthread_create, etc.). I started out reading some basic lecture slides (here's the sequel).
pthread_t could be any number of bytes. It could be a char, an int, a pointer, or a struct... But you neither need to know nor to care. If you need the size for allocation purposes, you use sizeof(pthread_t). The only type of variable you can assign it to is another pthread_t.
The compiler may or may not allocate the resources associated with the thread when you define a pthread_t. Again, you do not need to know nor to care, because you are required to call pthread_join (or pthread_detach) on any thread you create. As long as you follow the rules, the system will make sure it does not leak memory (or any other resource).
Attributes are admittedly a bit clumsy. They are held in an pthread_attr_t object, which again could be represented as an integer, pointer, or entire struct. You have to initialize it with pthread_attr_init and destroy it with pthread_attr_destroy. Between those two, you use various pthread_attr_... calls to set or clear attributes, and then you can pass it as part of one or more pthread_create calls to set the attributes of the new threads.
Different implementations can and will handle all of these things differently.
LLNL has a decent set of introductory information.
Look into pthread.h file to get more information. On my system, pthread_t is defined as an unsigned long int. But I guess this is platform dependent, since it is defined into bits/pthreadtype.h.
The function pthread_mutex_init allows you to specify a pointer to an attribute. But I have yet to find a good explanation of what pthread attributes are. I have always just supplied NULL. Is there a use to this argument?
The documentation, for those of you who forget it:
PTHREAD_MUTEX_INIT(3) BSD Library
Functions Manual
PTHREAD_MUTEX_INIT(3)
NAME
pthread_mutex_init -- create a mutex
SYNOPSIS
#include <pthread.h>
int
pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
DESCRIPTION
The pthread_mutex_init() function creates a new mutex, with attributes
specified
with attr. If attr is NULL, the default attributes are used.
The best place to find that information is from the POSIX standards pages.
A NULL mutex attribute gives you an implementation defined default attribute. If you want to know what you can do with attributes, check out the following reference and follow the pthread_mutexattr_* links in the SEE ALSO section. Usually, the default is a sensible set of attributes but it may vary between platforms, so I prefer to explicitly create mutexes with known attributes (better for portability).
This is for issue 7 of the standard, 1003.1-2008. The starting point for that is here. Clicking on Headers in the bottom left will allow you to navigate to the specific functionality (including pthreads.h).
The attributes allow you to set or get:
the type (deadlocking, deadlock-detecting, recursive, etc).
the robustness (what happens when you acquire a mutex and the original owner died while possessing it).
the process-shared attribute (for sharing a mutex across process boundaries).
the protocol (how a thread behaves in terms of priority when a higher-priority thread wants the mutex).
the priority ceiling (the priority at which the critical section will run, a way of preventing priority inversion).
And, for completeness, there's the init and destroy calls as well, not directly related to a specific attribute but used to create them.
All mutex attributes are set in a mutex attribute object by a function of the form:
int pthread_mutexattr_setname(pthread_attr_t *attr, Type t);
All mutex attributes are retrieved from a mutex attribute object by a function of the form:
int pthread_mutexattr_getname(const pthread_attr_t *attr, Type *t);
where name and Type are defined as in the table below:
Type and Name Description and Value(s)
int protocol Define the scheduling classes for mutex locks
PTHREAD_PRIO_NONE,PTHREAD_PRIO_PROTECT,
PTHREAD_PRIO_INHERIT
int pshared Defines whether a mutex is shared with other processes.
PTHREAD_PROCESS_SHARED, PTHREAD_PROCESS_PRIVATE
int prioceiling Used for mutex attribute priority ceiling values.
See POSIX.1 section 13
int type Application defined mutex locking
PTHREAD_MUTEX_NORMAL,PTHREAD_MUTEX_RECURSIVE,
PTHREAD_MUTEX_ERRORCHECK,PTHREAD_MUTEX_DEFAULT
If you scroll down the function listing for <pthread.h>, you will find a bunch of pthread_mutexattr_... functions, including an init, destroy and functions to set various attributes of a mutex. When you pass NULL, the mutex is created with suitable defaults for all these attributes, but if you need to modify specific attributes, you can construct a pthread_mutexattr_t structure and pass it in.
Applying NULL to this argument implies using the default argument.
So for some reasons you could want to change these default settings (using pthread_mutexattr_init).
The documentation explains all you need about these mutex settings.