valign.h 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /*
  2. * Variable alignment macros used to break up a larger chunk of memory into
  3. * smaller variables. Meant to be used to replace the use of Variable Length
  4. * Arrays In Structures (VLAIS)
  5. *
  6. * Copyright (C) 2012 Behan Webster <behanw@conversincode.com>
  7. */
  8. #ifndef _VALIGN_H_
  9. #define _VALIGN_H_
  10. /**
  11. * truncalign() - Align a memory address by truncation
  12. * @num: Address or size to align
  13. * @padwidth: Number of byte upon which to align
  14. *
  15. * Truncate an address or size to a particular memory alignment.
  16. * Used by truncalign().
  17. */
  18. #define truncalign(num, padwidth) ((long)(num) & ~((padwidth)-1))
  19. /**
  20. * padalign() - Align a memory address by padding
  21. * @num: Address or size to align
  22. * @padwidth: Number of byte upon which to align
  23. *
  24. * Pad out an address or size to a particular memory alignment
  25. * Used by paddedsize() and paddedstart().
  26. */
  27. #define padalign(num, padwidth) \
  28. truncalign((long)(num) + ((padwidth)-1), padwidth)
  29. /**
  30. * paddedsize() - Calculate the size of an chunk of aligned memory
  31. * @offset: Unaligned offset to the start of the chunk size being calculated
  32. * @num: The number of variables in the array of "type" (can be 1)
  33. * @type: The type of variables in the array
  34. * @nexttype: The type of the next variable in the large piece of memory
  35. *
  36. * Calculate the size that a variable (or array) will take as a part of a
  37. * larger piece of memory. Takes into account a potentially unaligned offset
  38. * into the larger piece of allocated memory, the alignment of the variable
  39. * type, and the alignement of the type of the variable to be used after that.
  40. *
  41. * Example: size_t l = paddedsize(1, 2, short, int);
  42. *
  43. * The example above would give you a padded size of 6 bytes: 2x 16-bit shorts,
  44. * starting at 2 bytes into the buffer (the offset of 1 byte being padded out
  45. * to 2 bytes) followed by 2 bytes of padding so that the next type (a 32-bit
  46. * int) would be 32-bit aligned. looking like this:
  47. *
  48. * 0: O.SS SS.. iiii
  49. * \-----/ <-- 2 shorts + 2 bytes of padding = size of 6 bytes
  50. *
  51. * O = The offset
  52. * . = Padding bytes
  53. * S = 2 shorts
  54. * i = int which will theoretically be next
  55. */
  56. #define paddedsize(offset, num, type, nexttype) (padalign((offset) \
  57. + (num) * sizeof(type), __alignof__(nexttype)) - (offset))
  58. /**
  59. * paddedstart() - Calculate the start of a chunk of aligned memory
  60. * @ptr: Pointer from which to calculate the start of the chunk
  61. * @offset: Offset from the ptr to the start of the chunk being calculated
  62. * @type: The type of variable in the chunk of memory
  63. *
  64. * Calculate the start address of a variable based on the offset from an
  65. * address, aligned based on the type of the variable specified.
  66. *
  67. * Example: char *data = kmalloc(size, GFP_KERNEL);
  68. * long *var = paddedstart(data, 12, long);
  69. *
  70. * The example above on a 64-bit machine would return the equivalent of
  71. * &buffer[16] since a long needs to be 8 byte aligned.
  72. *
  73. * 0: OOOO OOOO OOOO .... LLLL LLLL
  74. * ^ <-- The start address of the long
  75. * O = The offset
  76. * . = Padding bytes
  77. * L = The long
  78. */
  79. #define paddedstart(ptr, offset, type) \
  80. (type *)padalign((long)(ptr)+(offset), __alignof__(type))
  81. #endif