mm_graninfo.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /****************************************************************************
  2. * mm/mm_gran/mm_graninfo.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <assert.h>
  25. #include <nuttx/mm/gran.h>
  26. #include "mm_gran/mm_gran.h"
  27. #ifdef CONFIG_GRAN
  28. /****************************************************************************
  29. * Private Data
  30. ****************************************************************************/
  31. struct nibble_info_s
  32. {
  33. uint16_t nfree : 4; /* Total bits free in a nibble */
  34. uint16_t nlsfree : 4; /* Total contiguous LS bits free */
  35. uint16_t nmsfree : 4; /* Total contiguous MS bits free */
  36. uint16_t mxfree : 4; /* Largest internal contiguous bits free */
  37. };
  38. struct valinfo_s
  39. {
  40. uint8_t nfree; /* Total bits free in the byte/hword */
  41. uint8_t nlsfree; /* Total contiguous LS bits free */
  42. uint8_t nmsfree; /* Total contiguous MS bits free */
  43. uint8_t mxfree; /* Largest internal contiguous bits free */
  44. };
  45. /****************************************************************************
  46. * Private Data
  47. ****************************************************************************/
  48. static const struct nibble_info_s g_0bit_info[1] =
  49. {
  50. { /* 0 xxxx */
  51. 0, 0, 0, 0
  52. }
  53. };
  54. static const struct nibble_info_s g_1bit_info[2] =
  55. {
  56. { /* 0 xxx0 */
  57. 1, 1, 0, 0
  58. },
  59. { /* 1 xxx1 */
  60. 0, 0, 0, 0
  61. }
  62. };
  63. static const struct nibble_info_s g_2bit_info[4] =
  64. {
  65. { /* 0 xx00 */
  66. 2, 2, 0, 0
  67. },
  68. { /* 1 xx01 */
  69. 1, 0, 1, 0
  70. },
  71. { /* 2 xx10 */
  72. 1, 1, 0, 0
  73. },
  74. { /* 3 xx11 */
  75. 0, 0, 0, 0
  76. }
  77. };
  78. static const struct nibble_info_s g_3bit_info[8] =
  79. {
  80. { /* 0 x000 */
  81. 3, 3, 0, 0
  82. },
  83. { /* 1 x001 */
  84. 2, 0, 2, 0
  85. },
  86. { /* 2 x010 */
  87. 2, 1, 1, 0
  88. },
  89. { /* 3 x011 */
  90. 1, 0, 1, 0
  91. },
  92. { /* 4 x100 */
  93. 2, 2, 0, 0
  94. },
  95. { /* 5 x101 */
  96. 1, 0, 0, 1
  97. },
  98. { /* 6 x110 */
  99. 1, 1, 0, 0
  100. },
  101. { /* 7 x111 */
  102. 0, 0, 0, 0
  103. }
  104. };
  105. static const struct nibble_info_s g_4bit_info[16] =
  106. {
  107. { /* 0 0000 */
  108. 4, 4, 0, 0
  109. },
  110. { /* 1 0001 */
  111. 3, 0, 3, 0
  112. },
  113. { /* 2 0010 */
  114. 3, 1, 2, 0
  115. },
  116. { /* 3 0011 */
  117. 2, 0, 2, 0
  118. },
  119. { /* 4 0100 */
  120. 3, 2, 1, 0
  121. },
  122. { /* 5 0101 */
  123. 2, 0, 1, 1
  124. },
  125. { /* 6 0110 */
  126. 2, 1, 1, 0
  127. },
  128. { /* 7 0111 */
  129. 1, 0, 1, 0
  130. },
  131. { /* 8 1000 */
  132. 3, 3, 0, 0
  133. },
  134. { /* 9 1001 */
  135. 2, 0, 0, 2
  136. },
  137. { /* 10 1010 */
  138. 2, 1, 0, 1
  139. },
  140. { /* 11 1011 */
  141. 1, 0, 0, 1
  142. },
  143. { /* 12 1100 */
  144. 2, 2, 0, 0
  145. },
  146. { /* 13 1101 */
  147. 1, 0, 0, 1
  148. },
  149. { /* 14 1110 */
  150. 1, 1, 0, 0
  151. },
  152. { /* 15 1111 */
  153. 0, 0, 0, 0
  154. }
  155. };
  156. static const struct nibble_info_s *g_info_table[5] =
  157. {
  158. g_0bit_info,
  159. g_1bit_info,
  160. g_2bit_info,
  161. g_3bit_info,
  162. g_4bit_info
  163. };
  164. /****************************************************************************
  165. * Private Functions
  166. ****************************************************************************/
  167. /****************************************************************************
  168. * Name: gran_nibble_info
  169. *
  170. * Description:
  171. * Return information for a 4-bit value from the GAT.
  172. *
  173. * Input Parameters:
  174. * value - The 4-bit value
  175. * info - The location to return the hword info
  176. * nbits - Number of valid bits in value
  177. *
  178. * Returned Value:
  179. * None
  180. *
  181. ****************************************************************************/
  182. static void gran_nibble_info(uint8_t value, FAR struct valinfo_s *info,
  183. unsigned int nbits)
  184. {
  185. FAR const struct nibble_info_s *table = g_info_table[nbits];
  186. FAR const struct nibble_info_s *nibinfo;
  187. uint8_t mask;
  188. /* Look up the table entry */
  189. mask = ((1 << nbits) - 1);
  190. value &= mask;
  191. nibinfo = &table[value];
  192. /* Return expanded values */
  193. info->nfree = nibinfo->nfree;
  194. info->nlsfree = nibinfo->nlsfree;
  195. info->nmsfree = nibinfo->nmsfree;
  196. info->mxfree = nibinfo->mxfree;
  197. }
  198. /****************************************************************************
  199. * Name: gran_info_combine
  200. *
  201. * Description:
  202. * Combine new MS bit information with existing LS bit information.
  203. *
  204. * Input Parameters:
  205. * msinfo - The new MS bit information
  206. * msbits - Number of bits in MS piece
  207. * lsinfo - The existing LS bit information
  208. *
  209. * Returned Value:
  210. * None
  211. *
  212. ****************************************************************************/
  213. static void gran_info_combine(FAR const struct valinfo_s *msinfo,
  214. unsigned int msbits,
  215. FAR struct valinfo_s *lsinfo,
  216. unsigned int lsbits)
  217. {
  218. unsigned int midfree;
  219. /* Is there a region of free space isolated in the middle of the two
  220. * pieces?
  221. */
  222. if (lsinfo->nlsfree < lsbits && msinfo->nlsfree < msbits)
  223. {
  224. /* Yes... combine the MS free bits from the LS piece with the
  225. * LS free bits from the MS piece.
  226. */
  227. midfree = lsinfo->nmsfree + msinfo->nlsfree;
  228. }
  229. else
  230. {
  231. midfree = 0;
  232. }
  233. /* Update the total number of free bits in the combined pieces */
  234. lsinfo->nfree += msinfo->nfree;
  235. /* Figure out how many MS bits will now be free. First, is the MS piece
  236. * all free?
  237. */
  238. if (msinfo->nlsfree == msbits)
  239. {
  240. /* Yes.. is the LS piece also all free bits? */
  241. if (lsinfo->nlsfree == lsbits)
  242. {
  243. /* Yes.. the there are no MS free bits (only LS) */
  244. lsinfo->nmsfree = 0;
  245. }
  246. else
  247. {
  248. /* No.. then combine all of the bits from the MS piece with the
  249. * MS bits of the LS piece.
  250. */
  251. lsinfo->nmsfree += msbits;
  252. }
  253. }
  254. else
  255. {
  256. /* No.. then just replace the MS bits of the LS piece with the MS
  257. * bits from the new MS piece.
  258. */
  259. lsinfo->nmsfree = msinfo->nmsfree;
  260. }
  261. /* Figure out how many LS bits will now be free. First, is the LS piece
  262. * all free?
  263. */
  264. if (lsinfo->nlsfree == lsbits)
  265. {
  266. /* Yes.. then combine all of the bits from the LS piece with the
  267. * LS bits of the MS piece.
  268. */
  269. lsinfo->nlsfree += msinfo->nlsfree;
  270. }
  271. /* Now, what is the longest internal sequence of the free bits? It might
  272. * be original sequence of free bits in the LS piece. Or it might the
  273. * section of middle bits that got above.
  274. */
  275. if (midfree > lsinfo->mxfree)
  276. {
  277. lsinfo->mxfree = midfree;
  278. }
  279. /* Or it might the section of middle bits in the new MS piece */
  280. if (msinfo->mxfree > lsinfo->mxfree)
  281. {
  282. lsinfo->mxfree = msinfo->mxfree;
  283. }
  284. }
  285. /****************************************************************************
  286. * Name: gran_byte_info
  287. *
  288. * Description:
  289. * Return information a 8-bit value from the GAT.
  290. *
  291. * Input Parameters:
  292. * value - The 16-bit value
  293. * info - The location to return the hword info
  294. * nbits - Number of valid bits in value
  295. *
  296. * Returned Value:
  297. * None
  298. *
  299. ****************************************************************************/
  300. static void gran_byte_info(uint8_t value, FAR struct valinfo_s *info,
  301. unsigned int nbits)
  302. {
  303. uint8_t mask;
  304. if (nbits < 8)
  305. {
  306. mask = ((1 << nbits) - 1);
  307. value &= mask;
  308. }
  309. else
  310. {
  311. mask = 0xff;
  312. }
  313. /* Handle special cases */
  314. if (value == 0)
  315. {
  316. /* All free */
  317. info->nfree = nbits;
  318. info->nlsfree = nbits;
  319. info->nmsfree = 0;
  320. info->mxfree = 0;
  321. }
  322. else if (value == mask)
  323. {
  324. /* All allocated */
  325. info->nfree = 0;
  326. info->nlsfree = 0;
  327. info->nmsfree = 0;
  328. info->mxfree = 0;
  329. }
  330. else
  331. {
  332. /* Some allocated */
  333. gran_nibble_info(value & 0x0f, info, nbits > 4 ? 4 : nbits);
  334. if (nbits > 4)
  335. {
  336. struct valinfo_s msinfo;
  337. unsigned int msbits = nbits - 4;
  338. gran_nibble_info(value >> 4, &msinfo, msbits);
  339. gran_info_combine(&msinfo, msbits, info, 4);
  340. }
  341. }
  342. }
  343. /****************************************************************************
  344. * Name: gran_hword_info
  345. *
  346. * Description:
  347. * Return information a 16-bit value from the GAT.
  348. *
  349. * Input Parameters:
  350. * value - The 16-bit value
  351. * info - The location to return the hword info
  352. * nbits - Number of valid bits in value
  353. *
  354. * Returned Value:
  355. * None
  356. *
  357. ****************************************************************************/
  358. static void gran_hword_info(uint16_t value, FAR struct valinfo_s *info,
  359. unsigned int nbits)
  360. {
  361. uint16_t mask;
  362. if (nbits < 16)
  363. {
  364. mask = ((1 << nbits) - 1);
  365. value &= mask;
  366. }
  367. else
  368. {
  369. mask = 0xffff;
  370. }
  371. /* Handle special cases */
  372. if (value == 0)
  373. {
  374. /* All free */
  375. info->nfree = nbits;
  376. info->nlsfree = nbits;
  377. info->nmsfree = 0;
  378. info->mxfree = 0;
  379. }
  380. else if (value == mask)
  381. {
  382. /* All allocated */
  383. info->nfree = 0;
  384. info->nlsfree = 0;
  385. info->nmsfree = 0;
  386. info->mxfree = 0;
  387. }
  388. else
  389. {
  390. /* Some allocated */
  391. gran_byte_info((uint8_t)(value & 0xff), info, nbits > 8 ? 8 : nbits);
  392. if (nbits > 8)
  393. {
  394. struct valinfo_s msinfo;
  395. unsigned int msbits = nbits - 8;
  396. gran_byte_info((uint8_t)(value >> 8), &msinfo, msbits);
  397. gran_info_combine(&msinfo, msbits, info, 8);
  398. }
  399. }
  400. }
  401. /****************************************************************************
  402. * Public Functions
  403. ****************************************************************************/
  404. /****************************************************************************
  405. * Name: gran_info
  406. *
  407. * Description:
  408. * Return information about the granule heap.
  409. *
  410. * Input Parameters:
  411. * handle - The handle previously returned by gran_initialize
  412. * info - Memory location to return the gran allocator info.
  413. *
  414. * Returned Value:
  415. * Zero (OK) is returned on success; a negated errno value is return on
  416. * any failure.
  417. *
  418. ****************************************************************************/
  419. void gran_info(GRAN_HANDLE handle, FAR struct graninfo_s *info)
  420. {
  421. FAR struct gran_s *priv = (FAR struct gran_s *)handle;
  422. uint32_t mask;
  423. uint32_t value;
  424. uint16_t mxfree;
  425. unsigned int nbits;
  426. unsigned int granidx;
  427. unsigned int gatidx;
  428. int ret;
  429. DEBUGASSERT(priv != NULL && info != NULL);
  430. info->log2gran = priv->log2gran;
  431. info->ngranules = priv->ngranules;
  432. info->nfree = 0;
  433. info->mxfree = 0;
  434. mxfree = 0;
  435. /* Get exclusive access to the GAT */
  436. ret = gran_enter_critical(priv);
  437. if (ret < 0)
  438. {
  439. /* Should happen only on task cancellation */
  440. DEBUGASSERT(ret == -ECANCELED);
  441. return;
  442. }
  443. /* Traverse the granule allocation */
  444. for (granidx = 0; granidx < priv->ngranules; granidx += 32)
  445. {
  446. /* Get the GAT index associated with the granule table entry */
  447. gatidx = granidx >> 5;
  448. value = priv->gat[gatidx];
  449. /* The final entry is a special case */
  450. if ((granidx + 32) > priv->ngranules)
  451. {
  452. nbits = priv->ngranules - granidx;
  453. mask = ((1ul << nbits) - 1);
  454. value &= mask;
  455. }
  456. else
  457. {
  458. nbits = 32;
  459. mask = 0xffffffff;
  460. }
  461. /* Handle the 32-bit cases */
  462. if (value == mask)
  463. {
  464. /* All allocated. This will terminate any sequence of free
  465. * granules.
  466. */
  467. if (mxfree > info->mxfree)
  468. {
  469. info->mxfree = mxfree;
  470. }
  471. mxfree = 0;
  472. }
  473. else if (value == 0x00000000)
  474. {
  475. /* All free */
  476. info->nfree += nbits;
  477. mxfree += nbits;
  478. }
  479. else
  480. {
  481. struct valinfo_s hwinfo;
  482. /* Some allocated */
  483. gran_hword_info((uint16_t)(value & 0xffff), &hwinfo,
  484. nbits > 16 ? 16 : nbits);
  485. if (nbits > 16)
  486. {
  487. struct valinfo_s msinfo;
  488. unsigned int msbits = nbits - 16;
  489. gran_hword_info((uint16_t)(value >> 16), &msinfo, msbits);
  490. gran_info_combine(&msinfo, msbits, &hwinfo, 16);
  491. }
  492. /* Update the running free sequence of granules */
  493. if (hwinfo.nlsfree > 0)
  494. {
  495. mxfree += hwinfo.nlsfree;
  496. }
  497. /* If the entire word is not free, then update the maxfree free
  498. * sequence.
  499. */
  500. if (hwinfo.nlsfree < nbits)
  501. {
  502. /* Is the sequence internally free bits in the 32-bit value
  503. * longer than the running free sequence?
  504. */
  505. if (hwinfo.mxfree > mxfree)
  506. {
  507. mxfree = hwinfo.mxfree;
  508. }
  509. /* Is the running free sequence longer than the last sequence
  510. * that we saw?
  511. */
  512. if (mxfree > info->mxfree)
  513. {
  514. info->mxfree = mxfree;
  515. }
  516. /* Then restart with the free MS granules */
  517. mxfree = hwinfo.nmsfree;
  518. }
  519. /* Update the total number of free granules */
  520. info->nfree += hwinfo.nfree;
  521. }
  522. }
  523. /* Check if the last, unterminated sequence of free granules was the longest */
  524. if (mxfree > info->mxfree)
  525. {
  526. info->mxfree = mxfree;
  527. }
  528. gran_leave_critical(priv);
  529. }
  530. #endif /* CONFIG_GRAN */