bakery_lock.h 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*
  2. * Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #ifndef BAKERY_LOCK_H
  7. #define BAKERY_LOCK_H
  8. #include <platform_def.h>
  9. #define BAKERY_LOCK_MAX_CPUS PLATFORM_CORE_COUNT
  10. #ifndef __ASSEMBLER__
  11. #include <cdefs.h>
  12. #include <stdbool.h>
  13. #include <stdint.h>
  14. #include <lib/utils_def.h>
  15. /*****************************************************************************
  16. * Internal helpers used by the bakery lock implementation.
  17. ****************************************************************************/
  18. /* Convert a ticket to priority */
  19. static inline unsigned int bakery_get_priority(unsigned int t, unsigned int pos)
  20. {
  21. return (t << 8) | pos;
  22. }
  23. #define CHOOSING_TICKET U(0x1)
  24. #define CHOSEN_TICKET U(0x0)
  25. static inline bool bakery_is_choosing(unsigned int info)
  26. {
  27. return (info & 1U) == CHOOSING_TICKET;
  28. }
  29. static inline unsigned int bakery_ticket_number(unsigned int info)
  30. {
  31. return (info >> 1) & 0x7FFFU;
  32. }
  33. static inline uint16_t make_bakery_data(unsigned int choosing, unsigned int num)
  34. {
  35. unsigned int val = (choosing & 0x1U) | (num << 1);
  36. return (uint16_t) val;
  37. }
  38. /*****************************************************************************
  39. * External bakery lock interface.
  40. ****************************************************************************/
  41. #if USE_COHERENT_MEM
  42. /*
  43. * Bakery locks are stored in coherent memory
  44. *
  45. * Each lock's data is contiguous and fully allocated by the compiler
  46. */
  47. typedef struct bakery_lock {
  48. /*
  49. * The lock_data is a bit-field of 2 members:
  50. * Bit[0] : choosing. This field is set when the CPU is
  51. * choosing its bakery number.
  52. * Bits[1 - 15] : number. This is the bakery number allocated.
  53. */
  54. volatile uint16_t lock_data[BAKERY_LOCK_MAX_CPUS];
  55. } bakery_lock_t;
  56. #else
  57. /*
  58. * Bakery locks are stored in normal .bss memory
  59. *
  60. * Each lock's data is spread across multiple cache lines, one per CPU,
  61. * but multiple locks can share the same cache line.
  62. * The compiler will allocate enough memory for one CPU's bakery locks,
  63. * the remaining cache lines are allocated by the linker script
  64. */
  65. typedef struct bakery_info {
  66. /*
  67. * The lock_data is a bit-field of 2 members:
  68. * Bit[0] : choosing. This field is set when the CPU is
  69. * choosing its bakery number.
  70. * Bits[1 - 15] : number. This is the bakery number allocated.
  71. */
  72. volatile uint16_t lock_data;
  73. } bakery_info_t;
  74. typedef bakery_info_t bakery_lock_t;
  75. #endif /* __USE_COHERENT_MEM__ */
  76. static inline void bakery_lock_init(bakery_lock_t *bakery) {}
  77. void bakery_lock_get(bakery_lock_t *bakery);
  78. void bakery_lock_release(bakery_lock_t *bakery);
  79. #define DEFINE_BAKERY_LOCK(_name) bakery_lock_t _name __section(".bakery_lock")
  80. #define DECLARE_BAKERY_LOCK(_name) extern bakery_lock_t _name
  81. #endif /* __ASSEMBLER__ */
  82. #endif /* BAKERY_LOCK_H */