/* vim: set ts=8 sts=4 sw=4 tw=80 noet: */
/*======================================================================
Copyright (C) 2011 Walter Doekes <walter+tthsum@wjd.nu>
This file is part of tthsum.

tthsum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

tthsum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with tthsum.  If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "types.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>


/* The tiger_bp function uses unaligned 64 bit memory access on little
 * endian platforms. Tests on my x86_64 incur a 3.5% performance penalty
 * when we force aligned access. However, some platforms need alignment
 * to function properly (like the ARM).
 *
 * I tested doing 1024 byte reads on memory aligned such that it was
 * properly aligned for the tiger_bp function, but that caused the
 * system time to double: 6% performance penalty. */
static void conf_alignment() {
    /* Because it's hard to continue execution after a SIGBUS, we do
     * the misalignment check from a child process: this way both a 
     * SIGBUS and a value mismatch will add the -DREQUIRE_ALIGNMENT
     * preprocessor flag. */
    pid_t pid = fork();
    /* child */
    if (pid == 0) {
	uint64_t buf64[3];
	uint8_t *p;
	memcpy(buf64, "AAAAAAA" "BBBBBBBB" "CCCCCCCC", 24); /* 7+8+8+1 */
	p = (uint8_t*)&buf64[0] + 7;
	if (*((uint64_t*)p) != _ULL(0x4242424242424242))
	    _exit(1);
	_exit(0);
    /* parent */
    } else if (pid > 0) {
	int status;
	waitpid(pid, &status, 0);
	if (status != 0)
	    printf("-DREQUIRE_ALIGNMENT ");
    /* error */
    } else {
	perror("fork");
    }
}


int main() {
    conf_alignment();
    return 0;
}
