Proposal: More portable way to support 64bit platforms
Short description:
Current PostgreSQL implementation has some portability issues to
support 64bit platforms: pointer calculations using long is not
portable, for example on Windows x64 platform. We propose to use
intptr_t instead of long, which appears in in C99.
Details: intptr_t is defined in <stdint.h>. configure script already
has HAVE_STDINT_H but never uses it. This needs to be enabled.
Please note that Windows/VC++ defines intptr_t in <crtdefs.h>.
Included is a conceptual patch to use intptr_t. Comments are welcome.
Some notes for the patches:
access/common/heaptuple.c:
Casting using (long) is removed. It is no more necessary if we
introduce intptr_t.
include/c.h:
Many Alignment macros which use "long" are rewritten to use intrptr_t.
The patches is against PostgreSQL 8.4beta2. Regression test
passed. Windows x64 is ok even with shared_buffers = 3000MB.
Tested platforms are as follows:
Windows Server 2008 SP1 x64 + Visual Studio 2005
RHEL 4 x86_64 + gcc 3.4.6
FreeBSD 7.1 i386 + gcc 4.2.1
TODO:
Some problems may occur on older platforms, which do not have
stdint.h. In this case we need to add something like below to
include/port/*.h.
/* LP64, IPL64, ILP32, LP32 */
typedef long intptr_t;
typedef unsigned long uintptr_t;
/* LLP64 */
typedef long long intptr_t;
typedef unsigned long long uintptr_t;
Thanks,
--
Tsutomu Yamada // [email protected]
SRA OSS, Inc. Japan
diff -cwbr postgresql-8.4beta2-orig/src/backend/access/common/heaptuple.c
postgresql-8.4beta2-winx64/src/backend/access/common/heaptuple.c
*** postgresql-8.4beta2-orig/src/backend/access/common/heaptuple.c
2009-03-30 13:08:43.000000000 +0900
--- postgresql-8.4beta2-winx64/src/backend/access/common/heaptuple.c
2009-06-19 16:26:01.000000000 +0900
***************
*** 192,198 ****
if (att[i]->attbyval)
{
/* pass-by-value */
! data = (char *) att_align_nominal((long) data,
att[i]->attalign);
store_att_byval(data, values[i], att[i]->attlen);
data_length = att[i]->attlen;
}
--- 192,198 ----
if (att[i]->attbyval)
{
/* pass-by-value */
! data = (char *) att_align_nominal(data, att[i]->attalign);
store_att_byval(data, values[i], att[i]->attlen);
data_length = att[i]->attlen;
}
***************
*** 226,232 ****
else
{
/* full 4-byte header varlena */
! data = (char *) att_align_nominal((long) data,
att[i]->attalign);
data_length = VARSIZE(val);
memcpy(data, val, data_length);
--- 226,232 ----
else
{
/* full 4-byte header varlena */
! data = (char *) att_align_nominal(data,
att[i]->attalign);
data_length = VARSIZE(val);
memcpy(data, val, data_length);
***************
*** 243,249 ****
else
{
/* fixed-length pass-by-reference */
! data = (char *) att_align_nominal((long) data,
att[i]->attalign);
Assert(att[i]->attlen > 0);
data_length = att[i]->attlen;
memcpy(data, DatumGetPointer(values[i]), data_length);
--- 243,249 ----
else
{
/* fixed-length pass-by-reference */
! data = (char *) att_align_nominal(data,
att[i]->attalign);
Assert(att[i]->attlen > 0);
data_length = att[i]->attlen;
memcpy(data, DatumGetPointer(values[i]), data_length);
diff -cwbr postgresql-8.4beta2-orig/src/backend/access/hash/hashfunc.c
postgresql-8.4beta2-winx64/src/backend/access/hash/hashfunc.c
*** postgresql-8.4beta2-orig/src/backend/access/hash/hashfunc.c 2009-02-10
06:18:28.000000000 +0900
--- postgresql-8.4beta2-winx64/src/backend/access/hash/hashfunc.c
2009-06-18 22:37:46.000000000 +0900
***************
*** 319,325 ****
a = b = c = 0x9e3779b9 + len + 3923095;
/* If the source pointer is word-aligned, we use word-wide fetches */
! if (((long) k & UINT32_ALIGN_MASK) == 0)
{
/* Code path for aligned source data */
register const uint32 *ka = (const uint32 *) k;
--- 319,325 ----
a = b = c = 0x9e3779b9 + len + 3923095;
/* If the source pointer is word-aligned, we use word-wide fetches */
! if (((intptr_t) k & UINT32_ALIGN_MASK) == 0)
{
/* Code path for aligned source data */
register const uint32 *ka = (const uint32 *) k;
diff -cwbr postgresql-8.4beta2-orig/src/include/access/tupmacs.h
postgresql-8.4beta2-winx64/src/include/access/tupmacs.h
*** postgresql-8.4beta2-orig/src/include/access/tupmacs.h 2009-01-02
02:23:56.000000000 +0900
--- postgresql-8.4beta2-winx64/src/include/access/tupmacs.h 2009-06-19
16:20:02.000000000 +0900
***************
*** 142,148 ****
#define att_align_nominal(cur_offset, attalign) \
( \
((attalign) == 'i') ? INTALIGN(cur_offset) : \
! (((attalign) == 'c') ? (long) (cur_offset) : \
(((attalign) == 'd') ? DOUBLEALIGN(cur_offset) : \
( \
AssertMacro((attalign) == 's'), \
--- 142,148 ----
#define att_align_nominal(cur_offset, attalign) \
( \
((attalign) == 'i') ? INTALIGN(cur_offset) : \
! (((attalign) == 'c') ? (intptr_t) (cur_offset) : \
(((attalign) == 'd') ? DOUBLEALIGN(cur_offset) : \
( \
AssertMacro((attalign) == 's'), \
diff -cwbr postgresql-8.4beta2-orig/src/include/c.h
postgresql-8.4beta2-winx64/src/include/c.h
*** postgresql-8.4beta2-orig/src/include/c.h 2009-03-27 07:26:07.000000000
+0900
--- postgresql-8.4beta2-winx64/src/include/c.h 2009-06-19 15:43:35.000000000
+0900
***************
*** 82,87 ****
--- 82,91 ----
#include <SupportDefs.h>
#endif
+ #ifdef HAVE_STDINT_H
+ #include <stdint.h>
+ #endif
+
#if defined(WIN32) || defined(__CYGWIN__)
/* We have to redefine some system functions after they are included above. */
#include "pg_config_os.h"
***************
*** 492,498 ****
* True iff pointer is properly aligned to point to the given type.
*/
#define PointerIsAligned(pointer, type) \
! (((long)(pointer) % (sizeof (type))) == 0)
#define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid))
--- 496,502 ----
* True iff pointer is properly aligned to point to the given type.
*/
#define PointerIsAligned(pointer, type) \
! (((intptr_t)(pointer) % (sizeof (type))) == 0)
#define OidIsValid(objectId) ((bool) ((objectId) != InvalidOid))
***************
*** 538,544 ****
*/
#define TYPEALIGN(ALIGNVAL,LEN) \
! (((long) (LEN) + ((ALIGNVAL) - 1)) & ~((long) ((ALIGNVAL) - 1)))
#define SHORTALIGN(LEN) TYPEALIGN(ALIGNOF_SHORT, (LEN))
#define INTALIGN(LEN) TYPEALIGN(ALIGNOF_INT, (LEN))
--- 542,548 ----
*/
#define TYPEALIGN(ALIGNVAL,LEN) \
! (((intptr_t) (LEN) + ((ALIGNVAL) - 1)) & ~((intptr_t) ((ALIGNVAL) - 1)))
#define SHORTALIGN(LEN) TYPEALIGN(ALIGNOF_SHORT, (LEN))
#define INTALIGN(LEN) TYPEALIGN(ALIGNOF_INT, (LEN))
***************
*** 549,555 ****
#define BUFFERALIGN(LEN) TYPEALIGN(ALIGNOF_BUFFER, (LEN))
#define TYPEALIGN_DOWN(ALIGNVAL,LEN) \
! (((long) (LEN)) & ~((long) ((ALIGNVAL) - 1)))
#define SHORTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN))
#define INTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_INT, (LEN))
--- 553,559 ----
#define BUFFERALIGN(LEN) TYPEALIGN(ALIGNOF_BUFFER, (LEN))
#define TYPEALIGN_DOWN(ALIGNVAL,LEN) \
! (((intptr_t) (LEN)) & ~((intptr_t) ((ALIGNVAL) - 1)))
#define SHORTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_SHORT, (LEN))
#define INTALIGN_DOWN(LEN) TYPEALIGN_DOWN(ALIGNOF_INT, (LEN))
***************
*** 630,636 ****
int _val = (val); \
Size _len = (len); \
\
! if ((((long) _vstart) & LONG_ALIGN_MASK) == 0 && \
(_len & LONG_ALIGN_MASK) == 0 && \
_val == 0 && \
_len <= MEMSET_LOOP_LIMIT && \
--- 634,640 ----
int _val = (val); \
Size _len = (len); \
\
! if ((((intptr_t) _vstart) & LONG_ALIGN_MASK) == 0 && \
(_len & LONG_ALIGN_MASK) == 0 && \
_val == 0 && \
_len <= MEMSET_LOOP_LIMIT && \
diff -cwbr postgresql-8.4beta2-orig/src/include/pg_config.h.win32
postgresql-8.4beta2-winx64/src/include/pg_config.h.win32
*** postgresql-8.4beta2-orig/src/include/pg_config.h.win32 2009-05-15
11:18:27.000000000 +0900
--- postgresql-8.4beta2-winx64/src/include/pg_config.h.win32 2009-06-18
19:38:25.000000000 +0900
***************
*** 350,356 ****
/* #undef HAVE_SRANDOM */
/* Define to 1 if you have the <stdint.h> header file. */
! #define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
--- 350,356 ----
/* #undef HAVE_SRANDOM */
/* Define to 1 if you have the <stdint.h> header file. */
! /* #undef HAVE_STDINT_H */
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
diff -cwbr postgresql-8.4beta2-orig/src/interfaces/ecpg/ecpglib/data.c
postgresql-8.4beta2-winx64/src/interfaces/ecpg/ecpglib/data.c
*** postgresql-8.4beta2-orig/src/interfaces/ecpg/ecpglib/data.c 2009-01-15
20:52:55.000000000 +0900
--- postgresql-8.4beta2-winx64/src/interfaces/ecpg/ecpglib/data.c
2009-06-18 19:29:20.000000000 +0900
***************
*** 153,163 ****
if (pval)
{
if (varcharsize == 0 || varcharsize * offset >=
size)
! memcpy((char *) ((long) var + offset *
act_tuple),
pval, size);
else
{
! memcpy((char *) ((long) var + offset *
act_tuple),
pval, varcharsize * offset);
if (varcharsize * offset < size)
--- 153,163 ----
if (pval)
{
if (varcharsize == 0 || varcharsize * offset >=
size)
! memcpy((char *) ((intptr_t) var +
offset * act_tuple),
pval, size);
else
{
! memcpy((char *) ((intptr_t) var +
offset * act_tuple),
pval, varcharsize * offset);
if (varcharsize * offset < size)
***************
*** 392,401 ****
if (pval)
{
if (varcharsize == 0 ||
varcharsize > size)
! strncpy((char *)
((long) var + offset * act_tuple), pval, size + 1);
else
{
! strncpy((char *)
((long) var + offset * act_tuple), pval, varcharsize);
if (varcharsize < size)
{
--- 392,401 ----
if (pval)
{
if (varcharsize == 0 ||
varcharsize > size)
! strncpy((char *)
((intptr_t) var + offset * act_tuple), pval, size + 1);
else
{
! strncpy((char *)
((intptr_t) var + offset * act_tuple), pval, varcharsize);
if (varcharsize < size)
{
***************
*** 434,440 ****
if (pval)
{
struct ECPGgeneric_varchar
*variable =
! (struct ECPGgeneric_varchar *)
((long) var + offset * act_tuple);
variable->len = size;
if (varcharsize == 0)
--- 434,440 ----
if (pval)
{
struct ECPGgeneric_varchar
*variable =
! (struct ECPGgeneric_varchar *)
((intptr_t) var + offset * act_tuple);
variable->len = size;
if (varcharsize == 0)
diff -cwbr postgresql-8.4beta2-orig/src/pl/plperl/plperl.c
postgresql-8.4beta2-winx64/src/pl/plperl/plperl.c
*** postgresql-8.4beta2-orig/src/pl/plperl/plperl.c 2009-02-20
19:39:19.000000000 +0900
--- postgresql-8.4beta2-winx64/src/pl/plperl/plperl.c 2009-06-18
19:25:06.000000000 +0900
***************
*** 2192,2198 ****
************************************************************/
qdesc = (plperl_query_desc *) malloc(sizeof(plperl_query_desc));
MemSet(qdesc, 0, sizeof(plperl_query_desc));
! snprintf(qdesc->qname, sizeof(qdesc->qname), "%lx", (long) qdesc);
qdesc->nargs = argc;
qdesc->argtypes = (Oid *) malloc(argc * sizeof(Oid));
qdesc->arginfuncs = (FmgrInfo *) malloc(argc * sizeof(FmgrInfo));
--- 2192,2198 ----
************************************************************/
qdesc = (plperl_query_desc *) malloc(sizeof(plperl_query_desc));
MemSet(qdesc, 0, sizeof(plperl_query_desc));
! snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
qdesc->nargs = argc;
qdesc->argtypes = (Oid *) malloc(argc * sizeof(Oid));
qdesc->arginfuncs = (FmgrInfo *) malloc(argc * sizeof(FmgrInfo));
diff -cwbr postgresql-8.4beta2-orig/src/port/open.c
postgresql-8.4beta2-winx64/src/port/open.c
*** postgresql-8.4beta2-orig/src/port/open.c 2009-01-02 02:24:04.000000000
+0900
--- postgresql-8.4beta2-winx64/src/port/open.c 2009-06-18 19:22:08.000000000
+0900
***************
*** 123,129 ****
}
/* _open_osfhandle will, on error, set errno accordingly */
! if ((fd = _open_osfhandle((long) h, fileFlags & O_APPEND)) < 0)
CloseHandle(h); /* will not affect errno */
else if (fileFlags & (O_TEXT | O_BINARY) &&
_setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
--- 123,129 ----
}
/* _open_osfhandle will, on error, set errno accordingly */
! if ((fd = _open_osfhandle((intptr_t) h, fileFlags & O_APPEND)) < 0)
CloseHandle(h); /* will not affect errno */
else if (fileFlags & (O_TEXT | O_BINARY) &&
_setmode(fd, fileFlags & (O_TEXT | O_BINARY)) < 0)
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers