summaryrefslogtreecommitdiff
path: root/FreeRTOS/Demo/RISC-V_RV32_SiFive_HiFive1-RevB_FreedomStudio/freedom-metal/src/init.c
blob: 9d98737db1b06c78300126d7598f682b4ee34d65 (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
/* Copyright 2019 SiFive Inc. */
/* SPDX-License-Identifier: Apache-2.0 */

#include <metal/init.h>

/*
 * These function pointers are created by the linker script
 * in the .init_array section. The arrays defined by these
 * and end points are the set of functions defined by instances
 * of METAL_CONSTRUCTOR() and METAL_DESTRUCTOR().
 */
extern metal_constructor_t metal_constructors_start;
extern metal_constructor_t metal_constructors_end;
extern metal_destructor_t metal_destructors_start;
extern metal_destructor_t metal_destructors_end;

void metal_init(void) {
    /* Make sure the constructors only run once */
    static int init_done = 0;
    if (init_done) {
        return;
    }
    init_done = 1;

    if (&metal_constructors_end <= &metal_constructors_start) {
        return;
    }

    metal_constructor_t *funcptr = &metal_constructors_start;
    while (funcptr != &metal_constructors_end) {
        metal_constructor_t func = *funcptr;

        func();

        funcptr += 1;
    }
}

void metal_fini(void) {
    /* Make sure the destructors only run once */
    static int fini_done = 0;
    if (fini_done) {
        return;
    }
    fini_done = 1;

    if (&metal_destructors_end <= &metal_destructors_start) {
        return;
    }

    metal_destructor_t *funcptr = &metal_destructors_start;
    while (funcptr != &metal_destructors_end) {
        metal_destructor_t func = *funcptr;

        func();

        funcptr += 1;
    }
}

/*
 * metal_init_run() and metal_fini_run() are marked weak so that users
 * can redefine them for their own purposes, including to no-ops
 * in the case that users don't want the metal constructors or
 * destructors to run.
 */

void metal_init_run(void) __attribute__((weak));
void metal_init_run(void) { metal_init(); }

void metal_fini_run(void) __attribute__((weak));
void metal_fini_run(void) { metal_fini(); }