summaryrefslogtreecommitdiff
path: root/cpukit/libcsupport/src/cachecoherentalloc.c
blob: bf8167de889a42e0749c11bd795022905a97391f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/**
 * @file
 *
 * @ingroup ClassicCache
 */

/*
 * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
 *
 *  embedded brains GmbH
 *  Dornierstr. 4
 *  82178 Puchheim
 *  Germany
 *  <rtems@embedded-brains.de>
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rtems.org/license/LICENSE.
 */

#if HAVE_CONFIG_H
  #include "config.h"
#endif

#include <rtems.h>
#include <rtems/malloc.h>
#include <rtems/score/apimutex.h>
#include <rtems/score/heapimpl.h>
#include <rtems/score/sysstate.h>

static Heap_Control cache_coherent_heap_instance;

static Heap_Control *cache_coherent_heap;

void *rtems_cache_coherent_allocate(
  size_t size,
  uintptr_t alignment,
  uintptr_t boundary
)
{
  void *ptr;
  Heap_Control *heap;

  _RTEMS_Lock_allocator();

  heap = cache_coherent_heap;
  if ( heap == NULL ) {
    heap = RTEMS_Malloc_Heap;
  }

  ptr = _Heap_Allocate_aligned_with_boundary(
    heap,
    size,
    alignment,
    boundary
  );

  _RTEMS_Unlock_allocator();

  return ptr;
}

void rtems_cache_coherent_free( void *ptr )
{
  Heap_Control *heap;

  _RTEMS_Lock_allocator();

  heap = cache_coherent_heap;
  if ( heap != NULL ) {
    if ( _Heap_Free( heap, ptr ) ) {
      heap = NULL;
    } else {
      heap = RTEMS_Malloc_Heap;
    }
  } else {
    heap = RTEMS_Malloc_Heap;
  }

  if ( heap != NULL ) {
    _Heap_Free( heap, ptr );
  }

  _RTEMS_Unlock_allocator();
}

static void add_area(
  void *area_begin,
  uintptr_t area_size
)
{
  Heap_Control *heap = cache_coherent_heap;

  if ( heap == NULL ) {
    bool ok;

    heap = &cache_coherent_heap_instance;

    ok = _Heap_Initialize( heap, area_begin, area_size, 0 );
    if ( ok ) {
      cache_coherent_heap = heap;
    }
  } else {
    _Heap_Extend( heap, area_begin, area_size, 0 );
  }
}

void rtems_cache_coherent_add_area(
  void *area_begin,
  uintptr_t area_size
)
{
  if ( _System_state_Is_up( _System_state_Get()) ) {
    _RTEMS_Lock_allocator();

    add_area( area_begin, area_size );

    _RTEMS_Unlock_allocator();
  } else {
    add_area( area_begin, area_size );
  }
}