linux/drivers/staging/mali/DX910-SW-99002-r5p1-01rel0/driver/src/devicedrv/mali/linux/mali_osk_locks.h
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2010-2015 ARM Limited. All rights reserved.
   3 * 
   4 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
   5 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
   6 * 
   7 * A copy of the licence is included with the program, and can also be obtained from Free Software
   8 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   9 */
  10
  11/**
  12 * @file mali_osk_locks.h
  13 * Defines OS abstraction of lock and mutex
  14 */
  15#ifndef _MALI_OSK_LOCKS_H
  16#define _MALI_OSK_LOCKS_H
  17
  18#include <linux/spinlock.h>
  19#include <linux/rwsem.h>
  20#include <linux/mutex.h>
  21
  22#include <linux/slab.h>
  23
  24#include "mali_osk_types.h"
  25
  26#ifdef _cplusplus
  27extern "C" {
  28#endif
  29
  30        /* When DEBUG is enabled, this struct will be used to track owner, mode and order checking */
  31#ifdef DEBUG
  32        struct _mali_osk_lock_debug_s {
  33                u32 owner;
  34                _mali_osk_lock_flags_t orig_flags;
  35                _mali_osk_lock_order_t order;
  36                struct _mali_osk_lock_debug_s *next;
  37        };
  38#endif
  39
  40        /* Anstraction of spinlock_t */
  41        struct _mali_osk_spinlock_s {
  42#ifdef DEBUG
  43                struct _mali_osk_lock_debug_s checker;
  44#endif
  45                spinlock_t spinlock;
  46        };
  47
  48        /* Abstration of spinlock_t and lock flag which is used to store register's state before locking */
  49        struct _mali_osk_spinlock_irq_s {
  50#ifdef DEBUG
  51                struct _mali_osk_lock_debug_s checker;
  52#endif
  53
  54                spinlock_t spinlock;
  55                unsigned long flags;
  56        };
  57
  58        /* Abstraction of rw_semaphore in OS */
  59        struct _mali_osk_mutex_rw_s {
  60#ifdef DEBUG
  61                struct _mali_osk_lock_debug_s checker;
  62                _mali_osk_lock_mode_t mode;
  63#endif
  64
  65                struct rw_semaphore rw_sema;
  66        };
  67
  68        /* Mutex and mutex_interruptible functions share the same osk mutex struct */
  69        struct _mali_osk_mutex_s {
  70#ifdef DEBUG
  71                struct _mali_osk_lock_debug_s checker;
  72#endif
  73                struct mutex mutex;
  74        };
  75
  76#ifdef DEBUG
  77        /** @brief _mali_osk_locks_debug_init/add/remove() functions are declared when DEBUG is enabled and
  78         * defined in file mali_osk_locks.c. When LOCK_ORDER_CHECKING is enabled, calling these functions when we
  79         * init/lock/unlock a lock/mutex, we could track lock order of a given tid. */
  80        void _mali_osk_locks_debug_init(struct _mali_osk_lock_debug_s *checker, _mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order);
  81        void _mali_osk_locks_debug_add(struct _mali_osk_lock_debug_s *checker);
  82        void _mali_osk_locks_debug_remove(struct _mali_osk_lock_debug_s *checker);
  83
  84        /** @brief This function can return a given lock's owner when DEBUG     is enabled. */
  85        static inline u32 _mali_osk_lock_get_owner(struct _mali_osk_lock_debug_s *lock)
  86        {
  87                return lock->owner;
  88        }
  89#else
  90#define _mali_osk_locks_debug_init(x, y, z) do {} while (0)
  91#define _mali_osk_locks_debug_add(x) do {} while (0)
  92#define _mali_osk_locks_debug_remove(x) do {} while (0)
  93#endif
  94
  95        /** @brief Before use _mali_osk_spin_lock, init function should be used to allocate memory and initial spinlock*/
  96        static inline _mali_osk_spinlock_t *_mali_osk_spinlock_init(_mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order)
  97        {
  98                _mali_osk_spinlock_t *lock = NULL;
  99
 100                lock = kmalloc(sizeof(_mali_osk_spinlock_t), GFP_KERNEL);
 101                if (NULL == lock) {
 102                        return NULL;
 103                }
 104                spin_lock_init(&lock->spinlock);
 105                _mali_osk_locks_debug_init((struct _mali_osk_lock_debug_s *)lock, flags, order);
 106                return lock;
 107        }
 108
 109        /** @brief Lock a spinlock */
 110        static inline void  _mali_osk_spinlock_lock(_mali_osk_spinlock_t *lock)
 111        {
 112                BUG_ON(NULL == lock);
 113                spin_lock(&lock->spinlock);
 114                _mali_osk_locks_debug_add((struct _mali_osk_lock_debug_s *)lock);
 115        }
 116
 117        /** @brief Unlock a spinlock */
 118        static inline void _mali_osk_spinlock_unlock(_mali_osk_spinlock_t *lock)
 119        {
 120                BUG_ON(NULL == lock);
 121                _mali_osk_locks_debug_remove((struct _mali_osk_lock_debug_s *)lock);
 122                spin_unlock(&lock->spinlock);
 123        }
 124
 125        /** @brief Free a memory block which the argument lock pointed to and its type must be
 126         * _mali_osk_spinlock_t *. */
 127        static inline void _mali_osk_spinlock_term(_mali_osk_spinlock_t *lock)
 128        {
 129                /* Parameter validation  */
 130                BUG_ON(NULL == lock);
 131
 132                /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */
 133                kfree(lock);
 134        }
 135
 136        /** @brief Before _mali_osk_spinlock_irq_lock/unlock/term() is called, init function should be
 137         * called to initial spinlock and flags in struct _mali_osk_spinlock_irq_t. */
 138        static inline _mali_osk_spinlock_irq_t *_mali_osk_spinlock_irq_init(_mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order)
 139        {
 140                _mali_osk_spinlock_irq_t *lock = NULL;
 141                lock = kmalloc(sizeof(_mali_osk_spinlock_irq_t), GFP_KERNEL);
 142
 143                if (NULL == lock) {
 144                        return NULL;
 145                }
 146
 147                lock->flags = 0;
 148                spin_lock_init(&lock->spinlock);
 149                _mali_osk_locks_debug_init((struct _mali_osk_lock_debug_s *)lock, flags, order);
 150                return lock;
 151        }
 152
 153        /** @brief Lock spinlock and save the register's state */
 154        static inline void _mali_osk_spinlock_irq_lock(_mali_osk_spinlock_irq_t *lock)
 155        {
 156                unsigned long tmp_flags;
 157
 158                BUG_ON(NULL == lock);
 159                spin_lock_irqsave(&lock->spinlock, tmp_flags);
 160                lock->flags = tmp_flags;
 161                _mali_osk_locks_debug_add((struct _mali_osk_lock_debug_s *)lock);
 162        }
 163
 164        /** @brief Unlock spinlock with saved register's state */
 165        static inline void _mali_osk_spinlock_irq_unlock(_mali_osk_spinlock_irq_t *lock)
 166        {
 167                BUG_ON(NULL == lock);
 168                _mali_osk_locks_debug_remove((struct _mali_osk_lock_debug_s *)lock);
 169                spin_unlock_irqrestore(&lock->spinlock, lock->flags);
 170        }
 171
 172        /** @brief Destroy a given memory block which lock pointed to, and the lock type must be
 173         * _mali_osk_spinlock_irq_t *. */
 174        static inline void _mali_osk_spinlock_irq_term(_mali_osk_spinlock_irq_t *lock)
 175        {
 176                /* Parameter validation  */
 177                BUG_ON(NULL == lock);
 178
 179                /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */
 180                kfree(lock);
 181        }
 182
 183        /** @brief Before _mali_osk_mutex_rw_wait/signal/term() is called, we should call
 184         * _mali_osk_mutex_rw_init() to kmalloc a memory block and initial part of elements in it. */
 185        static inline _mali_osk_mutex_rw_t *_mali_osk_mutex_rw_init(_mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order)
 186        {
 187                _mali_osk_mutex_rw_t *lock = NULL;
 188
 189                lock = kmalloc(sizeof(_mali_osk_mutex_rw_t), GFP_KERNEL);
 190
 191                if (NULL == lock) {
 192                        return NULL;
 193                }
 194
 195                init_rwsem(&lock->rw_sema);
 196                _mali_osk_locks_debug_init((struct _mali_osk_lock_debug_s *)lock, flags, order);
 197                return lock;
 198        }
 199
 200        /** @brief When call _mali_osk_mutex_rw_wait/signal() functions, the second argument mode
 201         * should be assigned with value _MALI_OSK_LOCKMODE_RO or _MALI_OSK_LOCKMODE_RW */
 202        static inline void _mali_osk_mutex_rw_wait(_mali_osk_mutex_rw_t *lock, _mali_osk_lock_mode_t mode)
 203        {
 204                BUG_ON(NULL == lock);
 205                BUG_ON(!(_MALI_OSK_LOCKMODE_RO == mode || _MALI_OSK_LOCKMODE_RW == mode));
 206
 207                if (mode == _MALI_OSK_LOCKMODE_RO) {
 208                        down_read(&lock->rw_sema);
 209                } else {
 210                        down_write(&lock->rw_sema);
 211                }
 212
 213#ifdef DEBUG
 214                if (mode == _MALI_OSK_LOCKMODE_RW) {
 215                        lock->mode = mode;
 216                } else { /* mode == _MALI_OSK_LOCKMODE_RO */
 217                        lock->mode = mode;
 218                }
 219                _mali_osk_locks_debug_add((struct _mali_osk_lock_debug_s *)lock);
 220#endif
 221        }
 222
 223        /** @brief Up lock->rw_sema with up_read/write() accordinf argument mode's value. */
 224        static inline void  _mali_osk_mutex_rw_signal(_mali_osk_mutex_rw_t *lock, _mali_osk_lock_mode_t mode)
 225        {
 226                BUG_ON(NULL == lock);
 227                BUG_ON(!(_MALI_OSK_LOCKMODE_RO == mode || _MALI_OSK_LOCKMODE_RW == mode));
 228#ifdef DEBUG
 229                /* make sure the thread releasing the lock actually was the owner */
 230                if (mode == _MALI_OSK_LOCKMODE_RW) {
 231                        _mali_osk_locks_debug_remove((struct _mali_osk_lock_debug_s *)lock);
 232                        /* This lock now has no owner */
 233                        lock->checker.owner = 0;
 234                }
 235#endif
 236
 237                if (mode == _MALI_OSK_LOCKMODE_RO) {
 238                        up_read(&lock->rw_sema);
 239                } else {
 240                        up_write(&lock->rw_sema);
 241                }
 242        }
 243
 244        /** @brief Free a given memory block which lock pointed to and its type must be
 245         * _mali_sok_mutex_rw_t *. */
 246        static inline void _mali_osk_mutex_rw_term(_mali_osk_mutex_rw_t *lock)
 247        {
 248                /* Parameter validation  */
 249                BUG_ON(NULL == lock);
 250
 251                /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */
 252                kfree(lock);
 253        }
 254
 255        /** @brief Mutex & mutex_interruptible share the same init and term function, because they have the
 256         * same osk mutex struct, and the difference between them is which locking function they use */
 257        static inline _mali_osk_mutex_t *_mali_osk_mutex_init(_mali_osk_lock_flags_t flags, _mali_osk_lock_order_t order)
 258        {
 259                _mali_osk_mutex_t *lock = NULL;
 260
 261                lock = kmalloc(sizeof(_mali_osk_mutex_t), GFP_KERNEL);
 262
 263                if (NULL == lock) {
 264                        return NULL;
 265                }
 266                mutex_init(&lock->mutex);
 267
 268                _mali_osk_locks_debug_init((struct _mali_osk_lock_debug_s *)lock, flags, order);
 269                return lock;
 270        }
 271
 272        /** @brief  Lock the lock->mutex with mutex_lock_interruptible function */
 273        static inline _mali_osk_errcode_t _mali_osk_mutex_wait_interruptible(_mali_osk_mutex_t *lock)
 274        {
 275                _mali_osk_errcode_t err = _MALI_OSK_ERR_OK;
 276
 277                BUG_ON(NULL == lock);
 278
 279                if (mutex_lock_interruptible(&lock->mutex)) {
 280                        printk(KERN_WARNING "Mali: Can not lock mutex\n");
 281                        err = _MALI_OSK_ERR_RESTARTSYSCALL;
 282                }
 283
 284                _mali_osk_locks_debug_add((struct _mali_osk_lock_debug_s *)lock);
 285                return err;
 286        }
 287
 288        /** @brief Unlock the lock->mutex which is locked with mutex_lock_interruptible() function. */
 289        static inline void _mali_osk_mutex_signal_interruptible(_mali_osk_mutex_t *lock)
 290        {
 291                BUG_ON(NULL == lock);
 292                _mali_osk_locks_debug_remove((struct _mali_osk_lock_debug_s *)lock);
 293                mutex_unlock(&lock->mutex);
 294        }
 295
 296        /** @brief Lock the lock->mutex just with mutex_lock() function which could not be interruptted. */
 297        static inline void _mali_osk_mutex_wait(_mali_osk_mutex_t *lock)
 298        {
 299                BUG_ON(NULL == lock);
 300                mutex_lock(&lock->mutex);
 301                _mali_osk_locks_debug_add((struct _mali_osk_lock_debug_s *)lock);
 302        }
 303
 304        /** @brief Unlock the lock->mutex which is locked with mutex_lock() function. */
 305        static inline void _mali_osk_mutex_signal(_mali_osk_mutex_t *lock)
 306        {
 307                BUG_ON(NULL == lock);
 308                _mali_osk_locks_debug_remove((struct _mali_osk_lock_debug_s *)lock);
 309                mutex_unlock(&lock->mutex);
 310        }
 311
 312        /** @brief Free a given memory block which lock point. */
 313        static inline void _mali_osk_mutex_term(_mali_osk_mutex_t *lock)
 314        {
 315                /* Parameter validation  */
 316                BUG_ON(NULL == lock);
 317
 318                /* Linux requires no explicit termination of spinlocks, semaphores, or rw_semaphores */
 319                kfree(lock);
 320        }
 321
 322#ifdef _cplusplus
 323}
 324#endif
 325
 326#endif
 327