Bigstack.c
[目次 | 関数 | マクロ]
1|/**************************************************************************
2|* 1. <<< 大きいスタック (BigStack) >>>
3|*
4|*・ローカルスタック(ローカル変数に割り当てられるスタック領域)とは別に、
5|* 大きいメモリ領域を必要とする場合のスタックです。
6|*・このスタック領域は、グローバル変数の領域に取られます。
7|*・BigStack_max 変数に、最大の使用メモリサイズが格納されます。
8|* ただし、BIGSTACK_CHKSIZE を設定してください。
9|*
10|*【内部補足】
11|* --- スタックの構造 ---
12|*・BigStack のスタックは、スタック・ブロックが繰り返し入っている。
13|*・BigStack は、スタック・ブロックを単位としてスタックを開放する。
14|*・スタック・ブロックは、次のような構造になっている。
15|* [1つ前のスタック・ブロックの先頭アドレス][スタック領域]
16|* ↓次の図は無くしてしまいました (^^;
17|*
18|*
19|*・1.BigStack_start 関数で、1つ前のスタック・ブロックの先頭アドレスを記録して、
20|* 現在のスタック・ポインタの位置をメンバ変数に取っておき、 スタック・ポイ
21|* ンタをスタック領域に移動する。
22|*・2.BigStack_alloc 関数で、スタック領域をユーザのために確保して、 スタック・
23|* ポインタを進める。
24|*・3.BigStack_end 関数で、メンバ変数に取っておいた値を用いて、 スタック・
25|* ポインタを現在のスタック・ブロックの先頭に移動し、 その位置に記録してある
26|* 「1つ前のスタック・ブロックの先頭アドレス」を メンバ変数に取っておく。
27|*
28|*・最初のスタック・ブロックの「1つ前のスタック・ブロックの先頭アドレス」は、
29|* NULL が入る。
30|***************************************************************************/
31|
32|#include "mixer_precomp.h" /* Auto precompiled header, Look at mixer-... folder */
33|// #pragma hdrstop ("mixer_precomp")
34|
35|#define STDLIBS_INCLUDE
36|#define STDLIBS_INCLUDE_STDIO_H
37|#define STDLIBS_INCLUDE_STDLIB_H
38|
39|#if defined(USES_MXP_AUTOINC)
40| #include "bigstack.ah" /* Auto include header, Look at mixer-... folder */
41|#endif
42|
43|#ifdef count
44|#undef count
45|#endif
46|#ifdef sp
47|#undef sp
48|#endif
49|
50|
51|/*---------------------------------------------------------------------*/
52|/* 2. <<<◆ ビッグスタック・システム >>> */
53|/*---------------------------------------------------------------------*/
54|
55|BigStack BigStack_Sys_arrX; /* デフォルト */
56|
57|#ifdef USES_MULTASK
58|BigStack* BigStack_Sys_arr = &BigStack_Sys_arrX; /* 配列 */
59|int BigStack_Sys_mArr = 1;
60|#endif
61|
62|
63|
64|
65|/**************************************************************************
66|* 3. <<< [BigStack_Sys_init] BisStack システムを初期化する >>>
67|*【引数】
68|* ・BigStack* works; ワーク領域の先頭アドレス
69|* ・int mWork; 配列 work の最大要素数
70|*【補足】
71|*・シングルタスクでは呼び出す必要はありません。
72|*・本関数を呼び出す前に、MulTask_Sys_init を呼び出してください。
73|***************************************************************************/
74|#ifdef USES_MULTASK
75|void BigStack_Sys_init( BigStack* works, int mWork )
76|{
77| ASSERT( MulTask_Sys_isEnable() );
78|
79| BigStack_Sys_arr = works;
80| BigStack_Sys_mArr = mWork;
81|}
82|#endif
83|
84|
85|
86|/*---------------------------------------------------------------------*/
87|/* 4. <<<◆ ビッグスタック領域 >>> */
88|/*---------------------------------------------------------------------*/
89|
90|
91|
92|
93|
94|/**************************************************************************
95|* 5. <<< [BigStack_init_imp] 初期化する >>>
96|*【引数】
97|* ・char* mem; 大きいスタック領域の先頭アドレス
98|* ・size_t mem_sizeof; mem のメモリサイズ(バイト)
99|*【補足】
100|*・BigStack_init マクロから呼ばれます。
101|*・マルチタスク・システムでは、MulTask_Sys_init 関数を呼び出してから
102|* BigStack_init マクロを実行してください。
103|***************************************************************************/
104|void BigStack_init_imp( BigStack* m, char* mem, size_t mem_sizeof )
105|{
106| ERRORS_INITCHK( m, 0 );
107| ASSERT( ((int)mem & 3) == 0 ); /* ポインタも格納するため */
108|
109| m->mem = mem;
110| m->size = mem_sizeof;
111| m->sp = mem;
112| m->block1 = NULL;
113|}
114|
115|
116|
117|/**************************************************************************
118|* 6. <<< [BigStack_start_imp] スタックブロックの開始の指示 >>>
119|***************************************************************************/
120|void BigStack_start_imp( BigStack* m )
121|{
122| ERRORS_INITCHK( m, 1 );
123|
124| #ifndef NDEBUG
125| m->count ++;
126| #endif
127|
128| /* BigStack_block1 を mem 上に待避 */
129| *(char**)m->sp = m->block1;
130|
131| /* スタックブロックの区切りのメモリ位置を記録 */
132| m->block1 = m->sp;
133|
134| m->sp += sizeof( char* );
135|}
136|
137|
138|
139|/**************************************************************************
140|* 7. <<< [BigStack_alloc_imp] スタックからメモリ領域を確保する >>>
141|*【補足】
142|*・char* 型以外のメモリ領域として使う場合は、キャストしてください。
143|*【内部補足】
144|*・void* 型を返してもキャストは必要です。
145|***************************************************************************/
146|char* BigStack_alloc_imp( BigStack* m, unsigned int size )
147|{
148| char* ret = m->sp;
149|
150| ERRORS_INITCHK( m, 2 );
151|
152| #ifdef FOR_32BIT
153| size = ( (size + 3) & 0xFFFFFFFC ); /* 4の倍数に切上げ */
154| #else
155| size = ( (size + 3) & 0xFFFC ); /* 4の倍数に切上げ */
156| #endif
157|
158| if ( (m->sp - m->mem) + size > m->size ) {
159| error2_2( BigStack_Full, "BigStack 不足です (usable=%d, request=%d)",
160| m->size - (m->sp - m->mem), size );
161| }
162|
163| m->sp += size;
164|
165| #ifdef BIGSTACK_CHKSIZE
166| if ( m->sp > m->mem + m->max ) {
167| m->max = m->sp - m->mem;
168| }
169| #endif
170|
171| return ret;
172|}
173|
174|
175|
176|/**************************************************************************
177|* 8. <<< [BigStack_end_imp] スタックブロックの終了の指示 >>>
178|***************************************************************************/
179|void BigStack_end_imp( BigStack* m )
180|{
181| #ifndef NDEBUG
182| m->count --;
183| #endif
184| ERRORS_INITCHK( m, 1 );
185| ASSERT( m->block1 != NULL ); /* 2重エラーの1度目でブレークすればヒントになります */
186|
187| /* スタックポインタ sp を戻す */
188| m->sp = m->block1;
189|
190| /* m->block1 を戻す */
191| m->block1 = *(char**)m->sp;
192|}
193|
194|
195|
196|/**************************************************************************
197|* 9. <<< [BigStack_print_imp] デバッグ表示 >>>
198|***************************************************************************/
199|#ifndef ERRORS_CUT_DEBUG_TOOL
200|void BigStack_print_imp( BigStack* m )
201|{
202| Errors_printf( "BigStack: mem=%p, size=0x%X, sp=%p, block1=%p",
203| m->mem, m->size, m->sp, m->block1 );
204| #ifdef BIGSTACK_CHKSIZE
205| Errors_printf( "BigStack: max=0x%X", m->max );
206| #endif
207| #ifndef NDEBUG
208| Errors_printf( "BigStack: count=%d", m->count );
209| #endif
210|}
211|#endif
212|
213|
214|