int main(int argc, char* argv[]){
    uint64_t i, j;
    uint64_t ti=0;
    walkargs *threadargs;

    //printf("size of unsigned long long: %d\n", sizeof(unsigned long long));
    //printf("size of uint64_t: %d\n", sizeof(uint64_t));

    if ( argc > 1 ) {
        max = strtoull(argv[1], NULL, 0);
    }

    grid = malloc(max/8);
    memset(grid,0xaa,max/8); // 10101010 multiples of 2 are already set to 0
    memset(grid,0b10101100,1);

    threadargs = malloc(sqrt(max) * sizeof(walkargs));
    tid = malloc(sqrt(max) * sizeof(pthread_t));

    for (i=3; i<(uint64_t)sqrt(max); i++) {
        if ( ISON(i) ) {
            j = (uint64_t)pow(i,2);
            SETOFF(j);
            threadargs[ti].i=i;
            threadargs[ti].j=j;
            //		printf("creating thread %d to remove multiples of %d\n", ti, i);
            pthread_create(&tid[ti], NULL, walkovergrid, (void *)&threadargs[ti]);
            numthreads++;
            ti++;
            pthread_mutex_lock(&mutex);
            //		printf("numthreads is %d and maxthreads is %d\n", numthreads, maxthreads);
            while ( numthreads >= maxthreads ) {
                pthread_cond_wait(&cond, &mutex);
            }
            pthread_mutex_unlock(&mutex);
        }

    }
    // uncomment to print numbers
    //int t=0;
    //int rc;
    //for(t=ti-maxthreads; t<ti; t++){
    //    printf("In main: joining thread #%d\n", t);
    //    rc = pthread_join(tid[ti-t], NULL);
    //    if (rc) { fprintf(stderr, "failed to join thread #%ld - %s\n",
    //            (long)t, strerror(rc));
    //    exit(EXIT_FAILURE);
    //    }
    //}

    //for (i=0;i<max;i++) {
    //    if ( ISON(i) ) {
    //        printf("%d\n", i);
    //    }
    //}

    free(grid);

    pthread_exit(NULL);
}
static int sab8253x_startupS(struct sab_port *port)
{
	unsigned long flags;
	int retval = 0;
	
	save_flags(flags); cli();
	
	port->msgbufindex = 0;
	port->xmit_buf = NULL;
	port->buffergreedy = 0;
	
	if (port->flags & FLAG8253X_INITIALIZED) 
	{
		goto errout;
	}
	
	if (!port->regs) 
	{
		if (port->tty)
		{
			set_bit(TTY_IO_ERROR, &port->tty->flags);
		}
		retval = -ENODEV;
		goto errout;
	}
	/*
	 * Initialize the Hardware
	 */
	sab8253x_init_lineS(port);
	
#if 0				/* maybe should be conditional */
	if (port->tty->termios->c_cflag & CBAUD) 
	{
#endif
		/* Activate RTS */
		RAISE(port,rts);
		/* Activate DTR */
		RAISE(port,dtr);
#if 0
	}
#endif
	
	/*
	 * Initialize the modem signals values
	 */
	port->dcd.val=ISON(port,dcd);
	port->cts.val=ISON(port,cts);
	port->dsr.val=ISON(port,dsr);
	/*
	 * Finally, enable interrupts
	 */
	
	port->interrupt_mask0 = SAB82532_IMR0_RFS | SAB82532_IMR0_PCE |
		SAB82532_IMR0_PLLA | SAB82532_IMR0_RSC | SAB82532_IMR0_CDSC;
	
	/*((port->ccontrol.ccr2 & SAB82532_CCR2_TOE) ? SAB82532_IMR0_CDSC : 0); */
	
	WRITEB(port,imr0,port->interrupt_mask0);
	port->interrupt_mask1 = SAB82532_IMR1_EOP | SAB82532_IMR1_XMR |
		SAB82532_IMR1_TIN | SAB82532_IMR1_XPR;
	WRITEB(port, imr1, port->interrupt_mask1);
	port->all_sent = 1;
	
	if (port->tty)
	{
		clear_bit(TTY_IO_ERROR, &port->tty->flags);
	}
	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
	
	/*
	 * and set the speed of the serial port
	 */
	sab8253x_change_speedS(port);
	
	port->flags |= FLAG8253X_INITIALIZED;
	port->receive_chars = sab8253x_receive_charsS;
	port->transmit_chars = sab8253x_transmit_charsS;
	port->check_status = sab8253x_check_statusS;
	port->receive_test = (SAB82532_ISR0_RME | SAB82532_ISR0_RFO | SAB82532_ISR0_RPF);
	port->transmit_test = (SAB82532_ISR1_ALLS | SAB82532_ISR1_RDO | SAB82532_ISR1_XPR |
			       SAB82532_ISR1_XDU | SAB82532_ISR1_CSC);
	port->check_status_test = (SAB82532_ISR1_CSC);
	
	/*((port->ccontrol.ccr2 & SAB82532_CCR2_TOE) ? 0 : SAB82532_ISR0_CDSC));*/
	
	
	restore_flags(flags);
	return 0;
	
 errout:
	restore_flags(flags);
	return retval;
}
static void sab8253x_check_statusS(struct sab_port *port,
			    union sab8253x_irq_status *stat)
{
	struct tty_struct *tty = port->tty;
	int modem_change = 0;
	mctlsig_t         *sig;
	
	if (!tty)
	{
		return;
	}
	
	/* check_modem:*/
	/* Checking DCD */
	sig = &port->dcd;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,dcd);
		port->icount.dcd++;
		modem_change++;
	}
	/* Checking CTS */
	sig = &port->cts;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,cts);
		port->icount.cts++;
		modem_change++;
	}
	/* Checking DSR */
	sig = &port->dsr;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,dsr);
		port->icount.dsr++;
		modem_change++;
	}
	if (modem_change)
	{
		wake_up_interruptible(&port->delta_msr_wait);
	}
	
	sig = &port->dcd;
	if ((port->flags & FLAG8253X_CHECK_CD) &&
	    (stat->images[sig->irq] & sig->irqmask)) 
	{
		
		if (sig->val)
		{
			wake_up_interruptible(&port->open_wait);
		}
		else if (!((port->flags & FLAG8253X_CALLOUT_ACTIVE) &&
			   (port->flags & FLAG8253X_CALLOUT_NOHUP))) 
		{
#if 0				/* requires more investigation */
			MOD_INC_USE_COUNT;
			if (schedule_task(&port->tqueue_hangup) == 0)
			{
				MOD_DEC_USE_COUNT;
			}
#endif
		}
	}
	
	sig = &port->cts;
	if (port->flags & FLAG8253X_CTS_FLOW) 
	{				/* not setting this yet */
		if (port->tty->hw_stopped) 
		{
			if (sig->val) 
			{
				port->tty->hw_stopped = 0;
				sab8253x_sched_event(port, SAB8253X_EVENT_WRITE_WAKEUP);
				sab8253x_start_txS(port);
			}
		} 
		
		else 
		{
			if(!(getccr2configS(port) & SAB82532_CCR2_TOE))
			{
				if (!(sig->val)) 
				{
					port->tty->hw_stopped = 1;
				}
			}
		}
	}
}
int sab8253x_startupN(struct sab_port *port)
{
	unsigned long flags;
	int retval = 0;
	
	save_flags(flags); cli();
	
	if (port->flags & FLAG8253X_INITIALIZED) 
	{
		goto errout;
	}
	
	if (!port->regs) 
	{
		retval = -ENODEV;
		goto errout;
	}
	/*
	 * Initialize the Hardware
	 */
	sab8253x_init_lineS(port);	/* nothing in this function
					 * refers to tty structure */
	
	/* Activate RTS */
	RAISE(port,rts);
	/* Activate DTR */
	RAISE(port,dtr);
	/*
	 * Initialize the modem signals values
	 */
	port->dcd.val=ISON(port,dcd);
	port->cts.val=ISON(port,cts);
	port->dsr.val=ISON(port,dsr);
	/*
	 * Finally, enable interrupts
	 */
	
	port->interrupt_mask0 = SAB82532_IMR0_RFS | SAB82532_IMR0_PCE |
		SAB82532_IMR0_PLLA | SAB82532_IMR0_RSC | SAB82532_IMR0_CDSC;
	/*((port->ccontrol.ccr2 & SAB82532_CCR2_TOE) ? SAB82532_IMR0_CDSC : 0); */
	
	WRITEB(port,imr0,port->interrupt_mask0);
	port->interrupt_mask1 = SAB82532_IMR1_EOP | SAB82532_IMR1_XMR |
		SAB82532_IMR1_TIN | SAB82532_IMR1_XPR;
	WRITEB(port, imr1, port->interrupt_mask1);
	port->all_sent = 1;
	
	
	/*
	 * and set the speed of the serial port
	 */
	sab8253x_change_speedN(port);
	
	port->flags |= FLAG8253X_INITIALIZED; /* bad name for indicating to other functionalities status */
	port->receive_chars = sab8253x_receive_charsN;
	port->transmit_chars = sab8253x_transmit_charsS;
	port->check_status = sab8253x_check_statusN;
	port->receive_test = (SAB82532_ISR0_RME | SAB82532_ISR0_RFO | SAB82532_ISR0_RPF);
	port->transmit_test = (SAB82532_ISR1_ALLS | SAB82532_ISR1_RDO | SAB82532_ISR1_XPR |
			       SAB82532_ISR1_XDU | SAB82532_ISR1_CSC);
	port->check_status_test = (SAB82532_ISR1_CSC);
	
	/*((port->ccontrol.ccr2 & SAB82532_CCR2_TOE) ? 0 : SAB82532_ISR0_CDSC));*/
	
	restore_flags(flags);
	return 0;
	
 errout:
	restore_flags(flags);
	return retval;
}
static int sab8253x_block_til_readyN(SAB_PORT *port)
{
	DECLARE_WAITQUEUE(wait, current);
	int retval;
	int do_clocal = 0;
	unsigned long	flags;
	
	/*
	 * If the device is in the middle of being closed, then block
	 * until it's done, and then try again.
	 */
	if (port->flags & FLAG8253X_CLOSING)
	{
		if (port->flags & FLAG8253X_CLOSING)
		{
			interruptible_sleep_on(&port->close_wait);
		}
#ifdef SERIAL_DO_RESTART
		if (port->flags & FLAG8253X_HUP_NOTIFY)
		{
			return -EAGAIN;
		}
		else
		{
			return -ERESTARTSYS;
		}
#else
		return -EAGAIN;
#endif
	}
	
	/*
	 * this is not a callout device
	 */
	
	/* suppose callout active */
	if (port->flags & FLAG8253X_CALLOUT_ACTIVE) 
	{
		if (port->normal_termios.c_cflag & CLOCAL)
		{
			do_clocal = 1;
		}
	} 
	
	/*
	 * Block waiting for the carrier detect and the line to become
	 * free (i.e., not in use by the callout).  While we are in
	 * this loop, port->count is dropped by one, so that
	 * sab8253x_close() knows when to free things.  We restore it upon
	 * exit, either normal or abnormal.
	 */
	retval = 0;
	add_wait_queue(&port->open_wait, &wait);
	port->blocked_open++;
	while (1) 
	{
		save_flags(flags); cli();
		if (!(port->flags & FLAG8253X_CALLOUT_ACTIVE))
		{
			RAISE(port,dtr);
			RAISE(port,rts);	/* maybe not correct for sync */
			/*
			 * ??? Why changing the mode here? 
			 *  port->regs->rw.mode |= SAB82532_MODE_FRTS;
			 *  port->regs->rw.mode &= ~(SAB82532_MODE_RTS);
			 */
		}
		restore_flags(flags);
		current->state = TASK_INTERRUPTIBLE;
		if (!(port->flags & FLAG8253X_INITIALIZED)) 
		{
#ifdef SERIAL_DO_RESTART
			if (port->flags & FLAG8253X_HUP_NOTIFY)
			{
				retval = -EAGAIN;
			}
			else
			{
				retval = -ERESTARTSYS;	
			}
#else
			retval = -EAGAIN;
#endif
			break;
		}
		if (!(port->flags & FLAG8253X_CALLOUT_ACTIVE) &&
		    !(port->flags & FLAG8253X_CLOSING) &&
		    (do_clocal || ISON(port,dcd))) 
		{
			break;
		}
#ifdef DEBUG_OPEN
		printk("block_til_readyN:2 flags = 0x%x\n",port->flags);
#endif
		if (signal_pending(current)) 
		{
			retval = -ERESTARTSYS;
			break;
		}
		schedule();
	}
	current->state = TASK_RUNNING;
	remove_wait_queue(&port->open_wait, &wait);
	port->blocked_open--;
	if (retval)
	{
		return retval;
	}
	port->flags |= FLAG8253X_NORMAL_ACTIVE; /* is this a good flag? */
	return 0;
}
static void sab8253x_check_statusN(struct sab_port *port,
				   union sab8253x_irq_status *stat)
{
	int modem_change = 0;
	mctlsig_t         *sig;
	
	
	if (stat->images[ISR0_IDX] & SAB82532_ISR0_RFO) 
	{
		port->icount.buf_overrun++;
	}
	
	/* Checking DCD */
	sig = &port->dcd;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,dcd);
		port->icount.dcd++;
		modem_change++;
	}
	/* Checking CTS */
	sig = &port->cts;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,cts);
		port->icount.cts++;
		modem_change++;
	}
	/* Checking DSR */
	sig = &port->dsr;
	if (stat->images[sig->irq] & sig->irqmask) 
	{
		sig->val = ISON(port,dsr);
		port->icount.dsr++;
		modem_change++;
	}
	if (modem_change)
	{
		wake_up_interruptible(&port->delta_msr_wait);
	}
	
	sig = &port->dcd;
	if ((port->flags & FLAG8253X_CHECK_CD) &&
	    (stat->images[sig->irq] & sig->irqmask)) 
	{
		
		if (sig->val)
		{
			netif_carrier_on(port->dev);
		}
		else if (!((port->flags & FLAG8253X_CALLOUT_ACTIVE) &&
			   (port->flags & FLAG8253X_CALLOUT_NOHUP))) 
		{
			netif_carrier_off(port->dev);
		}
	}
#if 0				/* need to think about CTS/RTS stuff for a network driver */
	sig = &port->cts;
	if (port->flags & FLAG8253X_CTS_FLOW) 
	{				/* not setting this yet */
		if (port->tty->hw_stopped) 
		{
			if (sig->val) 
			{
				
				port->tty->hw_stopped = 0;
				sab8253x_sched_event(port, RS_EVENT_WRITE_WAKEUP);
				port->interrupt_mask1 &= ~(SAB82532_IMR1_XPR);
				WRITEB(port, imr1, port->interrupt_mask1);
				sab8253x_start_txS(port);
			}
		} 
		else 
		{
			if (!(sig->val)) 
			{
				port->tty->hw_stopped = 1;
			}
		}
	}
#endif
}