1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project
3*344aa361SAndroid Build Coastguard Worker *
4*344aa361SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*344aa361SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*344aa361SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*344aa361SAndroid Build Coastguard Worker *
8*344aa361SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*344aa361SAndroid Build Coastguard Worker *
10*344aa361SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*344aa361SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*344aa361SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*344aa361SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*344aa361SAndroid Build Coastguard Worker * limitations under the License.
15*344aa361SAndroid Build Coastguard Worker */
16*344aa361SAndroid Build Coastguard Worker
17*344aa361SAndroid Build Coastguard Worker #include <err.h>
18*344aa361SAndroid Build Coastguard Worker #include <errno.h>
19*344aa361SAndroid Build Coastguard Worker #include <kernel/thread.h>
20*344aa361SAndroid Build Coastguard Worker #include <stdlib.h>
21*344aa361SAndroid Build Coastguard Worker #include <trusty/libc_state.h>
22*344aa361SAndroid Build Coastguard Worker #include "locale_impl.h"
23*344aa361SAndroid Build Coastguard Worker
libc_state_create(void)24*344aa361SAndroid Build Coastguard Worker static struct libc_state* libc_state_create(void) {
25*344aa361SAndroid Build Coastguard Worker struct libc_state* state = calloc(1, sizeof(struct libc_state));
26*344aa361SAndroid Build Coastguard Worker if (state != NULL) {
27*344aa361SAndroid Build Coastguard Worker state->errno_val = 0;
28*344aa361SAndroid Build Coastguard Worker state->locale = C_LOCALE;
29*344aa361SAndroid Build Coastguard Worker }
30*344aa361SAndroid Build Coastguard Worker return state;
31*344aa361SAndroid Build Coastguard Worker }
32*344aa361SAndroid Build Coastguard Worker
libc_state_thread_init(thread_t * t)33*344aa361SAndroid Build Coastguard Worker int libc_state_thread_init(thread_t* t) {
34*344aa361SAndroid Build Coastguard Worker if (t == NULL) {
35*344aa361SAndroid Build Coastguard Worker return ERR_INVALID_ARGS;
36*344aa361SAndroid Build Coastguard Worker }
37*344aa361SAndroid Build Coastguard Worker struct libc_state* state = libc_state_create();
38*344aa361SAndroid Build Coastguard Worker if (state == NULL) {
39*344aa361SAndroid Build Coastguard Worker return ERR_NO_RESOURCES;
40*344aa361SAndroid Build Coastguard Worker }
41*344aa361SAndroid Build Coastguard Worker thread_tls_set(t, TLS_ENTRY_LIBC, (uintptr_t)state);
42*344aa361SAndroid Build Coastguard Worker return NO_ERROR;
43*344aa361SAndroid Build Coastguard Worker }
44*344aa361SAndroid Build Coastguard Worker
libc_state_thread_free(thread_t * t)45*344aa361SAndroid Build Coastguard Worker int libc_state_thread_free(thread_t* t) {
46*344aa361SAndroid Build Coastguard Worker if (t == NULL) {
47*344aa361SAndroid Build Coastguard Worker return ERR_INVALID_ARGS;
48*344aa361SAndroid Build Coastguard Worker }
49*344aa361SAndroid Build Coastguard Worker struct libc_state* state =
50*344aa361SAndroid Build Coastguard Worker (struct libc_state*)thread_tls_get(t, TLS_ENTRY_LIBC);
51*344aa361SAndroid Build Coastguard Worker ASSERT(state);
52*344aa361SAndroid Build Coastguard Worker free(state);
53*344aa361SAndroid Build Coastguard Worker
54*344aa361SAndroid Build Coastguard Worker /* Replace the old TLS entry with NULL to remove the dangling pointer and
55*344aa361SAndroid Build Coastguard Worker * catch double frees */
56*344aa361SAndroid Build Coastguard Worker thread_tls_set(t, TLS_ENTRY_LIBC, (uintptr_t)NULL);
57*344aa361SAndroid Build Coastguard Worker
58*344aa361SAndroid Build Coastguard Worker return NO_ERROR;
59*344aa361SAndroid Build Coastguard Worker }
60*344aa361SAndroid Build Coastguard Worker
current_thread_libc_state(void)61*344aa361SAndroid Build Coastguard Worker struct libc_state* current_thread_libc_state(void) {
62*344aa361SAndroid Build Coastguard Worker return (struct libc_state*)tls_get(TLS_ENTRY_LIBC);
63*344aa361SAndroid Build Coastguard Worker }
64*344aa361SAndroid Build Coastguard Worker
__errno_location(void)65*344aa361SAndroid Build Coastguard Worker int* __errno_location(void) {
66*344aa361SAndroid Build Coastguard Worker struct libc_state* state = current_thread_libc_state();
67*344aa361SAndroid Build Coastguard Worker DEBUG_ASSERT(state);
68*344aa361SAndroid Build Coastguard Worker return &state->errno_val;
69*344aa361SAndroid Build Coastguard Worker }
70*344aa361SAndroid Build Coastguard Worker
71*344aa361SAndroid Build Coastguard Worker weak_alias(__errno_location, ___errno_location);
72