split.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. /*
  2. * Copyright 2011 Institute of Communication and Computer Systems (ICCS)
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. */
  17. #include "freelist/split.h"
  18. #include "dmmlib/config.h"
  19. #ifdef WITH_KNOBS
  20. #include "dmmlib/dmmlib.h"
  21. #endif /* WITH_KNOBS */
  22. #include "other.h"
  23. #include "freelist/block_header_funcs.h"
  24. #include "freelist/ordering_policy.h"
  25. void split(freelist_rb_t *raw_block, block_header_t *ptr, size_t req_size) {
  26. size_t new_size;
  27. size_t min_split_size;
  28. block_header_t *new_block;
  29. #ifdef COALESCE_AFTER_SPLIT
  30. size_t max_coal_size;
  31. block_header_t *next_block;
  32. size_t current_next_size;
  33. next_block = get_dlnext(raw_block, ptr);
  34. #endif /* COALESCE_AFTER_SPLIT */
  35. /* Align the requested size */
  36. req_size = req_padding(req_size);
  37. /* Check what would be the size of the new block if we split the current
  38. * one.
  39. * Note: new_size is a size_t, so compare first in order to prevent an
  40. * underflow.
  41. */
  42. if(get_size(ptr) > req_size + HEADER_SIZE) {
  43. new_size = get_size(ptr) - req_size - HEADER_SIZE;
  44. } else {
  45. new_size = 0;
  46. }
  47. #ifdef SPLITTING_FIXED
  48. min_split_size = MIN_SPLIT_SIZE;
  49. #endif /* SPLITTING_FIXED */
  50. #ifdef SPLITTING_VARIABLE
  51. min_split_size = (size_t) systemallocator.dmm_knobs.min_split_size;
  52. #endif /* SPLITTING_VARIABLE */
  53. if(new_size < min_split_size) {
  54. return;
  55. }
  56. new_block = (block_header_t *)((char *)ptr + req_size + HEADER_SIZE);
  57. if(raw_block->border_ptr == ptr) {
  58. raw_block->border_ptr = new_block;
  59. }
  60. /* Resize the previous, to be used block */
  61. set_size_and_used(raw_block, ptr, req_size);
  62. #ifdef COALESCE_AFTER_SPLIT
  63. /* Try to coalesce with the next block if it is free */
  64. #ifdef COALESCING_FIXED
  65. max_coal_size = MAX_COAL_SIZE;
  66. #endif /* COALESCING_FIXED */
  67. #ifdef COALESCING_VARIABLE
  68. max_coal_size = systemallocator.dmm_knobs.max_coal_size;
  69. #endif /* COALESCING_VARIABLE */
  70. if(next_block != NULL && is_free(next_block) == true) {
  71. current_next_size = new_size + get_size(next_block) + HEADER_SIZE;
  72. if(current_next_size <= max_coal_size) {
  73. REMOVE_FSLLIST(raw_block, next_block);
  74. if(raw_block->border_ptr == next_block) {
  75. raw_block->border_ptr = new_block;
  76. }
  77. new_size = current_next_size;
  78. }
  79. }
  80. #endif /* COALESCE_AFTER_SPLIT */
  81. set_size_and_free(raw_block, new_block, new_size);
  82. ADD_BLOCK(new_block);
  83. }