mt_memalign.c
4.53 KB
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
/*
=============================================================================
Copyright (C) 1997-1999 NINTENDO Co.,Ltd.
$RCSfile: mt_memalign.c,v $
$Revision: 1.1.1.1 $
$Date: 2002/10/30 02:07:09 $
=============================================================================
関数名:mt_memalign
-----------------------------------------------------------------------------
書式: #include <malloc.h>
void *mt_memalign(int alignment, size_t size);
説明: マルチスレッド対応の memalign()。
引数や戻り値、その他の説明については、memalign() と同じなので、
そちらの説明を参照すること。
-----------------------------------------------------------------------------
*/
#include <ultra64.h>
#include "string.h"
#include "malloc.h"
#include "_malloc.h"
void *mt_memalign(int alignment, size_t size)
{
int size2;
unsigned int *next2, *p, *r;
unsigned char *c;
struct mallocST *malloc_st_ptr;
OSIntMask svintmask ;
if ((int)malloc_ptr == -1) return NULL;
if (!size) return NULL;
svintmask = osSetIntMask( OS_IM_NONE ) ; /* 全ての割り込みを不許可 */
if( alignment <= 16 ){
/* r を使い回している */
r = (unsigned int *)_malloc( malloc_ptr, size ) ;
osSetIntMask( svintmask ) ; /* 割り込みマスクを復帰 */
return (void *)r ;
}
malloc_st_ptr = (struct mallocST *)malloc_ptr;
size += 15;
size &= (~15);
size2 = 0;
next2 = 0;
while(1) {
if (!malloc_st_ptr->flag) {
c = (unsigned char *)malloc_st_ptr;
c += (MALLOC_HEADSIZE + alignment - 1);
c = (unsigned char *)((int)c & (~(alignment-1)));
if (c >= (unsigned char *)malloc_st_ptr+MALLOC_HEADSIZE && c+size<(unsigned char *)malloc_st_ptr+malloc_st_ptr->size) {
// アライメント後のアドレスがブロック内?
if ((size2 > malloc_st_ptr->size) || !size2) {
r = (unsigned int *)c;
p = (unsigned int *)malloc_st_ptr;
size2 = malloc_st_ptr->size;
next2 = malloc_st_ptr->next;
}
}
}
if (!(malloc_st_ptr->next)) break;
malloc_st_ptr = (struct mallocST *)malloc_st_ptr->next;
}
if (size2) {
if (p != (unsigned int *)malloc_ptr) {
if ((int)r - (int)p<= 32) { // アライメントのために前に空くメモリが16バイト以下なら前の容量を増やす。
if (r-p >15) {
malloc_st_ptr = (struct mallocST *)malloc_ptr;
while(1) {
if (malloc_st_ptr->next == 0) break;
if (malloc_st_ptr->next == p) {
malloc_st_ptr->next = r-MALLOC_HEADSIZE;
malloc_st_ptr->size += 16;
break;
}
malloc_st_ptr = (struct mallocST *)malloc_st_ptr->next;
}
}
} else { // アライメント後の前に16バイト以上の大きな空きメモリが出来たのでブロックを作成
malloc_st_ptr = (struct mallocST *)p;
malloc_st_ptr->next = r -(MALLOC_HEADSIZE/sizeof(unsigned int *));
malloc_st_ptr->size = (int)r - (int)p - MALLOC_HEADSIZE * 2;
malloc_st_ptr->flag = 0;
}
} else {
malloc_st_ptr = (struct mallocST *)p;
malloc_st_ptr->next = r - (MALLOC_HEADSIZE / sizeof(int *));
malloc_st_ptr->size = (r - p)*sizeof(int) - MALLOC_HEADSIZE * 2;
malloc_st_ptr->flag = 0;
}
c = (char *)r;
c -= MALLOC_HEADSIZE;
malloc_st_ptr = (struct mallocST *)c;
if (size2>=size+MALLOC_HEADSIZE+16) {
malloc_st_ptr->next = (unsigned int *)((unsigned int)r + size); /* メモリ確保 */
malloc_st_ptr->size = size;
malloc_st_ptr->flag = 1;
malloc_st_ptr = (struct mallocST *)malloc_st_ptr->next; /* あまりメモリ開放 */
malloc_st_ptr->next = next2;
malloc_st_ptr->size = size2 - size - (r - p) * sizeof(int);
malloc_st_ptr->flag = 0;
} else {
malloc_st_ptr->next = next2;
malloc_st_ptr->size = (int)(next2 - r);
malloc_st_ptr->flag = 1;
}
osSetIntMask( svintmask ) ; /* 割り込みマスクを復帰 */
return (unsigned char *)r;
}
osSetIntMask( svintmask ) ; /* 割り込みマスクを復帰 */
return NULL;
}