rems-project / cerberus

Cerberus C semantics

Home Page:https://www.cl.cam.ac.uk/~pes20/cerberus/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[CN] Locks, concurrency, higer-order resources (Can a spec provide different resources based on the argument?)

peterohanley opened this issue · comments

For a mutex, I'd like mutex_lock(foo) to provide different resources than mutex_lock(bar). This is easy if different functions are called for each mutex, but this is not possible because the specific mutex called might be dynamic. However, I think the kind of mutex is still static. Consider a mutex field guarding the rest of a struct. How can this be done?

Hm, I think this generally falls under "implementing support for locks", which is fair. Do you have a non-lock example of adjusting the resource based on argument?

There's a big pile of papers in separation logic talking about how to do this (I added a couple to the pile). Ideally we want to be able to reason something like this:

mutex *make_mutex(predicate P) 
/*@ 
requires 
  take pre = P; 
ensures 
  take post_ = is_mutex(return, P); 
@*/

take_mutex(mutex *m) 
/*@ 
requires 
  take mut = is_mutex(m, P); 
ensures 
  take mut_ = locked_mutex(m, P); 
  take post_ = P; 
@*/ 

release_mutex(mutex *m) 
/*@ 
requires 
  take locked = locked_mutex(m,P); 
  take inv = P; 
ensures 
  take mut_ = is_mutex(m,P); 
@*/ 

That is, we can create locks with arbitrary predicate arguments and then create them dynamically. This is a big motivation for fancy higher-order logics like Iris, which let you do this in a sensible way.

However, obviously CN doesn't have any such support. The best you can do, I would imagine, is specialize the mutex to each instance of the predicate. That is, you have a mutex for each resource P, Q, whatever... This is an instance where having multiple specs for the same function could be useful, although you could always copy the code I suppose and name the lock per the protected resource.

Let me clarify. We're aware of the need to implement locks and Neel and Christopher have some ideas on how to implement them. What my question was about any non-lock examples of higher order resources? Or multiple specifications? Just to shape any design discussions.

This is related to locks but not exactly locks: concurrency management. Functions enter_critical, exit_critical, and yield. Yield will eventually return but probably no locks should be held while yielding. Entering a critical section disables preemption, and a lot of APIs like this also return some kind of value that should be passed to exit_critical. Yield must not be called in a critical section. It seems that yield must require the absence of an in_critical resource, or there must be a normal_execution resource in the environment all the time. Probably the latter because then you can have in_isr, in_signalhandler, etc. FreeRTOS for example has a lot of duplicated functions based on whether the caller is in ISR context or not. This token needs to be threaded around everywhere unfortunately.

I've been reading this thread, and thinking about utilizing mutexes in our code. To start, is there a definition for the mutex type?

Thanks!

Yes, but there isn't a mutex typedef, and I'm not sure which to use since CN's buggy about structs and unions: https://stackoverflow.com/questions/30585375/what-is-the-type-of-pthread-mutex-t

It looks like cerberus special cases it. runtime/libc/include/posix/pthread.h:

#define pthread_mutex_t       __cerbty_pthread_mutex_t

What happens when you try to run cn on the example code?

That definition works, but I'm looking for a definition of is_mutex, Locked, and predicate. Or are there already cerberus definitions for those somewhere?

You need to write new ones for your use case. A canned definition can't be written in cn at this time (this issue)

Ah, so I'm trying to understand what cerberus has already implemented. So the pthread_mutex_t type is defined, but not pthread_mutex_lock? Any other operations on pthread_mutex_t defined?

Thanks!