= The user_lock library = [[PageOutline]] The [source:soft/giet_vm/giet_libs/user_lock.c user_lock.c] and [source:soft/giet_vm/giet_libs/user_lock.h user_lock.h] files define two types of locks: * '''user_lock_t''' : this lock uses a ticket allocation mechanism to enforce fairness and avoid live-locks. This lock is located in one single cluster, and the placement can be controlled by defining a specific vseg in the application mapping. * '''sqt_lock_t''' : this distributed lock can be used to avoid quadratic latency, when the protected resource is shared by a large number or threads. The SQT (Synchronization Quad-Tree) is distributed on all clusters of the mesh. Each lock (user_lock_t object, or distributed sqt_lock_node_t) occupies a complete 64 bytes cache line to avoid false sharing. The '''user_lock_t''' and '''sqt_lock_t''' being shared by several threads, should be defined as a global variable in the application code. == Atomic access functions == Both types of locks use the atomic_increment() function, that can be directly used by the applications. === unsigned int '''atomic_increment'''( unsigned int* shared, unsigned int increment) === This blocking function uses a LL/SC to atomically increment a shared variable. * '''ptr''' : pointer on the shared variable * '''increment''' : increment value. == Simple lock access functions === '''void lock_init'''( user_lock_t * lock ) === This function should be called by one single task. * '''lock''' : pointer on the user_lock_t structure. === '''void lock_acquire'''( user_lock_t * lock ) === This blocking function returns only when the lock has been successfully taken. * '''lock''' : pointer on the user_lock_t structure. === '''void lock_release'''( user_lock_t * lock ) === This function releases the lock. It must be called by a task after a successful lock_acquire(). * '''lock''' : pointer on the user_lock_t structure. == Distributed lock access functions == The SQT topology is completely defined by the (x_size / y_size) parameters, with the following constraints: * The involved clusters form a mesh(x_size * y_size). * The lower left involved cluster is cluster(0,0). * All involved clusters must contain a heap_x_y vseg declared in the mapping. * The number of involved tasks in a given cluster is the same for all involved clusters. === '''void sqt_lock_init'''( sqt_lock_t * lock ) === This function should be called by one single task. * '''lock''' : pointer on the sqt_lock_t structure. === '''void sqt_lock_acquire'''( sqt_lock_t * lock ) === This blocking function returns only when all locks of the distributed tree have been successfully taken. * '''lock''' : pointer on the sqt_lock_t structure. === '''void sqt_lock_release'''( sqt_lock_t * lock ) === This function releases the lock. It must be called by a task after a successful lock_acquire(). * '''lock''' : pointer on the sqt_lock_t structure.