* cygtls.cc (san::leave/x86_64): Implement.

* cygtls.h (class tls_pathbuf): Move counter variables into a union.
	Add 64 bit element _counters covering both counter variables to
	optimize save and restore operations.
	(class san/x86_64): Only store single 64 bit value.
	(san::san/x86_64): Implement.
	(san::leave/x86_64): Only declare here, as returns_twice function.
	Explain why.
	(class san/i686): Change type of _c_cnt and _w_cnt to uint32_t.
	(__try/x86_64): Move definition of __sebastian after the first memory
	barrier.  Drop __sebastian.setup call.
This commit is contained in:
Corinna Vinschen 2014-08-25 19:47:44 +00:00
parent 5578cc4b73
commit 12b244394c
3 changed files with 41 additions and 17 deletions

View File

@ -1,3 +1,17 @@
2014-08-25 Corinna Vinschen <corinna@vinschen.de>
* cygtls.cc (san::leave/x86_64): Implement.
* cygtls.h (class tls_pathbuf): Move counter variables into a union.
Add 64 bit element _counters covering both counter variables to
optimize save and restore operations.
(class san/x86_64): Only store single 64 bit value.
(san::san/x86_64): Implement.
(san::leave/x86_64): Only declare here, as returns_twice function.
Explain why.
(class san/i686): Change type of _c_cnt and _w_cnt to uint32_t.
(__try/x86_64): Move definition of __sebastian after the first memory
barrier. Drop __sebastian.setup call.
2014-08-25 Corinna Vinschen <corinna@vinschen.de>
* cygtls.cc (_cygtls::remove): Revert previous patch.

View File

@ -200,3 +200,11 @@ _cygtls::remove (DWORD wait)
cygheap->remove_tls (this, wait);
remove_wq (wait);
}
#ifdef __x86_64__
void san::leave ()
{
/* Restore tls_pathbuf counters in case of error. */
_my_tls.locals.pathbufs._counters = _cnt;
}
#endif

View File

@ -51,8 +51,15 @@ class tls_pathbuf
/* Make sure that c_cnt and w_cnt are always the first two members of this
class, and never change the size (32 bit), unless you also change the
mov statements in sigbe! */
uint32_t c_cnt;
uint32_t w_cnt;
union
{
struct
{
uint32_t c_cnt;
uint32_t w_cnt;
};
uint64_t _counters;
};
char *c_buf[TP_NUM_C_BUFS];
WCHAR *w_buf[TP_NUM_W_BUFS];
@ -291,28 +298,24 @@ extern _cygtls *_sig_tls;
#ifdef __x86_64__
class san
{
unsigned _c_cnt;
unsigned _w_cnt;
uint64_t _cnt;
public:
void setup () __attribute__ ((always_inline))
san () __attribute__ ((always_inline))
{
_c_cnt = _my_tls.locals.pathbufs.c_cnt;
_w_cnt = _my_tls.locals.pathbufs.w_cnt;
}
void leave () __attribute__ ((always_inline))
{
/* Restore tls_pathbuf counters in case of error. */
_my_tls.locals.pathbufs.c_cnt = _c_cnt;
_my_tls.locals.pathbufs.w_cnt = _w_cnt;
_cnt = _my_tls.locals.pathbufs._counters;
}
/* This is the first thing called in the __except handler. The attribute
"returns_twice" makes sure that GCC disregards any register value set
earlier in the function, so this call serves as a register barrier. */
void leave () __attribute__ ((returns_twice));
};
#else
class san
{
san *_clemente;
jmp_buf _context;
unsigned _c_cnt;
unsigned _w_cnt;
uint32_t _c_cnt;
uint32_t _w_cnt;
public:
int setup () __attribute__ ((always_inline))
{
@ -356,8 +359,8 @@ public:
#define __try \
{ \
__label__ __l_try, __l_except, __l_endtry; \
san __sebastian; \
__mem_barrier; \
san __sebastian; \
__asm__ goto ("\n" \
" .seh_handler _ZN9exception7myfaultEP17_EXCEPTION_RECORDPvP8_CONTEXTP19_DISPATCHER_CONTEXT, @except \n" \
" .seh_handlerdata \n" \
@ -365,7 +368,6 @@ public:
" .rva %l[__l_try],%l[__l_endtry],%l[__l_except],%l[__l_except] \n" \
" .seh_code \n" \
: : : : __l_try, __l_endtry, __l_except); \
__sebastian.setup (); \
{ \
__l_try: \
__mem_barrier;