stack_inl.h 5.89 KB
Newer Older
gejun's avatar
gejun committed
1
// bthread - A M:N threading library to make applications more concurrent.
gejun's avatar
gejun committed
2
// Copyright (c) 2014 Baidu, Inc.
gejun's avatar
gejun committed
3 4 5 6 7 8 9 10 11 12 13 14
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
gejun's avatar
gejun committed
15 16 17 18

// Author: Ge,Jun (gejun@baidu.com)
// Date: Sun Sep  7 22:37:39 CST 2014

gejun's avatar
gejun committed
19 20
#ifndef BTHREAD_ALLOCATE_STACK_INL_H
#define BTHREAD_ALLOCATE_STACK_INL_H
gejun's avatar
gejun committed
21 22 23 24 25 26 27 28 29 30 31

DECLARE_int32(guard_page_size);
DECLARE_int32(tc_stack_small);
DECLARE_int32(tc_stack_normal);

namespace bthread {

struct MainStackClass {};

struct SmallStackClass {
    static int* stack_size_flag;
gejun's avatar
gejun committed
32 33
    // Older gcc does not allow static const enum, use int instead.
    static const int stacktype = (int)STACK_TYPE_SMALL;
gejun's avatar
gejun committed
34 35 36 37
};

struct NormalStackClass {
    static int* stack_size_flag;
gejun's avatar
gejun committed
38
    static const int stacktype = (int)STACK_TYPE_NORMAL;
gejun's avatar
gejun committed
39 40 41 42
};

struct LargeStackClass {
    static int* stack_size_flag;
gejun's avatar
gejun committed
43
    static const int stacktype = (int)STACK_TYPE_LARGE;
gejun's avatar
gejun committed
44 45
};

gejun's avatar
gejun committed
46 47
template <typename StackClass> struct StackFactory {
    struct Wrapper : public ContextualStack {
gejun's avatar
gejun committed
48
        explicit Wrapper(void (*entry)(intptr_t)) {
gejun's avatar
gejun committed
49 50 51
            if (allocate_stack_storage(&storage, *StackClass::stack_size_flag,
                                       FLAGS_guard_page_size) != 0) {
                storage.zeroize();
gejun's avatar
gejun committed
52 53 54
                context = NULL;
                return;
            }
gejun's avatar
gejun committed
55 56
            context = bthread_make_fcontext(storage.bottom, storage.stacksize, entry);
            stacktype = (StackType)StackClass::stacktype;
gejun's avatar
gejun committed
57 58
        }
        ~Wrapper() {
gejun's avatar
gejun committed
59 60 61 62
            if (context) {
                context = NULL;
                deallocate_stack_storage(&storage);
                storage.zeroize();
gejun's avatar
gejun committed
63 64 65 66
            }
        }
    };
    
gejun's avatar
gejun committed
67
    static ContextualStack* get_stack(void (*entry)(intptr_t)) {
68
        return butil::get_object<Wrapper>(entry);
gejun's avatar
gejun committed
69 70
    }
    
gejun's avatar
gejun committed
71
    static void return_stack(ContextualStack* sc) {
72
        butil::return_object(static_cast<Wrapper*>(sc));
gejun's avatar
gejun committed
73 74 75
    }
};

gejun's avatar
gejun committed
76 77 78 79
template <> struct StackFactory<MainStackClass> {
    static ContextualStack* get_stack(void (*)(intptr_t)) {
        ContextualStack* s = new (std::nothrow) ContextualStack;
        if (NULL == s) {
gejun's avatar
gejun committed
80 81
            return NULL;
        }
gejun's avatar
gejun committed
82 83 84 85
        s->context = NULL;
        s->stacktype = STACK_TYPE_MAIN;
        s->storage.zeroize();
        return s;
gejun's avatar
gejun committed
86 87
    }
    
gejun's avatar
gejun committed
88 89
    static void return_stack(ContextualStack* s) {
        delete s;
gejun's avatar
gejun committed
90 91 92
    }
};

gejun's avatar
gejun committed
93
inline ContextualStack* get_stack(StackType type, void (*entry)(intptr_t)) {
gejun's avatar
gejun committed
94 95 96 97
    switch (type) {
    case STACK_TYPE_PTHREAD:
        return NULL;
    case STACK_TYPE_SMALL:
gejun's avatar
gejun committed
98
        return StackFactory<SmallStackClass>::get_stack(entry);
gejun's avatar
gejun committed
99
    case STACK_TYPE_NORMAL:
gejun's avatar
gejun committed
100
        return StackFactory<NormalStackClass>::get_stack(entry);
gejun's avatar
gejun committed
101
    case STACK_TYPE_LARGE:
gejun's avatar
gejun committed
102
        return StackFactory<LargeStackClass>::get_stack(entry);
gejun's avatar
gejun committed
103
    case STACK_TYPE_MAIN:
gejun's avatar
gejun committed
104
        return StackFactory<MainStackClass>::get_stack(entry);
gejun's avatar
gejun committed
105 106 107 108
    }
    return NULL;
}

gejun's avatar
gejun committed
109 110
inline void return_stack(ContextualStack* s) {
    if (NULL == s) {
gejun's avatar
gejun committed
111 112
        return;
    }
gejun's avatar
gejun committed
113
    switch (s->stacktype) {
gejun's avatar
gejun committed
114 115 116 117
    case STACK_TYPE_PTHREAD:
        assert(false);
        return;
    case STACK_TYPE_SMALL:
gejun's avatar
gejun committed
118
        return StackFactory<SmallStackClass>::return_stack(s);
gejun's avatar
gejun committed
119
    case STACK_TYPE_NORMAL:
gejun's avatar
gejun committed
120
        return StackFactory<NormalStackClass>::return_stack(s);
gejun's avatar
gejun committed
121
    case STACK_TYPE_LARGE:
gejun's avatar
gejun committed
122
        return StackFactory<LargeStackClass>::return_stack(s);
gejun's avatar
gejun committed
123
    case STACK_TYPE_MAIN:
gejun's avatar
gejun committed
124
        return StackFactory<MainStackClass>::return_stack(s);
gejun's avatar
gejun committed
125 126 127
    }
}

gejun's avatar
gejun committed
128 129 130 131
inline void jump_stack(ContextualStack* from, ContextualStack* to) {
    bthread_jump_fcontext(&from->context, to->context, 0/*not skip remained*/);
}

gejun's avatar
gejun committed
132 133
}  // namespace bthread

134
namespace butil {
gejun's avatar
gejun committed
135

gejun's avatar
gejun committed
136
template <> struct ObjectPoolBlockMaxItem<
gejun's avatar
gejun committed
137
    bthread::StackFactory<bthread::LargeStackClass>::Wrapper> {
gejun's avatar
gejun committed
138
    static const size_t value = 64;
gejun's avatar
gejun committed
139
};
gejun's avatar
gejun committed
140
template <> struct ObjectPoolBlockMaxItem<
gejun's avatar
gejun committed
141
    bthread::StackFactory<bthread::NormalStackClass>::Wrapper> {
gejun's avatar
gejun committed
142
    static const size_t value = 64;
gejun's avatar
gejun committed
143 144
};

gejun's avatar
gejun committed
145
template <> struct ObjectPoolBlockMaxItem<
gejun's avatar
gejun committed
146
    bthread::StackFactory<bthread::SmallStackClass>::Wrapper> {
gejun's avatar
gejun committed
147
    static const size_t value = 64;
gejun's avatar
gejun committed
148 149
};

gejun's avatar
gejun committed
150
template <> struct ObjectPoolFreeChunkMaxItem<
gejun's avatar
gejun committed
151
    bthread::StackFactory<bthread::SmallStackClass>::Wrapper> {
gejun's avatar
gejun committed
152 153 154 155 156
    inline static size_t value() {
        return (FLAGS_tc_stack_small <= 0 ? 0 : FLAGS_tc_stack_small);
    }
};

gejun's avatar
gejun committed
157
template <> struct ObjectPoolFreeChunkMaxItem<
gejun's avatar
gejun committed
158
    bthread::StackFactory<bthread::NormalStackClass>::Wrapper> {
gejun's avatar
gejun committed
159 160 161 162 163
    inline static size_t value() {
        return (FLAGS_tc_stack_normal <= 0 ? 0 : FLAGS_tc_stack_normal);
    }
};

gejun's avatar
gejun committed
164
template <> struct ObjectPoolFreeChunkMaxItem<
gejun's avatar
gejun committed
165
    bthread::StackFactory<bthread::LargeStackClass>::Wrapper> {
gejun's avatar
gejun committed
166 167 168 169
    inline static size_t value() { return 1UL; }
};

template <> struct ObjectPoolValidator<
gejun's avatar
gejun committed
170
    bthread::StackFactory<bthread::LargeStackClass>::Wrapper> {
gejun's avatar
gejun committed
171
    inline static bool validate(
gejun's avatar
gejun committed
172 173
        const bthread::StackFactory<bthread::LargeStackClass>::Wrapper* w) {
        return w->context != NULL;
gejun's avatar
gejun committed
174 175 176 177
    }
};

template <> struct ObjectPoolValidator<
gejun's avatar
gejun committed
178
    bthread::StackFactory<bthread::NormalStackClass>::Wrapper> {
gejun's avatar
gejun committed
179
    inline static bool validate(
gejun's avatar
gejun committed
180 181
        const bthread::StackFactory<bthread::NormalStackClass>::Wrapper* w) {
        return w->context != NULL;
gejun's avatar
gejun committed
182 183 184 185
    }
};

template <> struct ObjectPoolValidator<
gejun's avatar
gejun committed
186
    bthread::StackFactory<bthread::SmallStackClass>::Wrapper> {
gejun's avatar
gejun committed
187
    inline static bool validate(
gejun's avatar
gejun committed
188 189
        const bthread::StackFactory<bthread::SmallStackClass>::Wrapper* w) {
        return w->context != NULL;
gejun's avatar
gejun committed
190 191 192
    }
};
    
193
}  // namespace butil
gejun's avatar
gejun committed
194

gejun's avatar
gejun committed
195
#endif  // BTHREAD_ALLOCATE_STACK_INL_H